[Cmake-commits] CMake branch, next, updated. v2.8.11.2-3718-g21e61f0

Ben Boeckel ben.boeckel at kitware.com
Tue Aug 6 16:11:58 EDT 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  21e61f055931d7e561b4ef4cab60ea7797fdf809 (commit)
       via  56e770fa9288a5801322f36442483e96cffc8a61 (commit)
       via  cf4364cbb2e8640c50c30ab2267ef0c685dd4af9 (commit)
       via  6379d729a2b19a2d8391ca7cf39008372aaf0a71 (commit)
       via  9df982572ca2c3f22e3625f204b8e5c155d4f3d6 (commit)
       via  f92f3ffc7648de08005600f14465433cfba84bbc (commit)
       via  faad4e183d81e0ed5c6e1ae64ac23db95837ef71 (commit)
       via  8c0a98e0dabb9fab5fa31a8b9aac2f8191ba46ed (commit)
       via  dc1c6546704bc277e7c884a53e538ee5d8b831c8 (commit)
       via  8d1fc6c88946f6dd18c6f17d4f6f8825547972ef (commit)
      from  2f5bb2df18b65553041433ca34ad84a65d34e9c5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=21e61f055931d7e561b4ef4cab60ea7797fdf809
commit 21e61f055931d7e561b4ef4cab60ea7797fdf809
Merge: 2f5bb2d 56e770f
Author:     Ben Boeckel <ben.boeckel at kitware.com>
AuthorDate: Tue Aug 6 16:11:55 2013 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Tue Aug 6 16:11:55 2013 -0400

    Merge topic 'dev/fix-variable-watch-crash' into next
    
    56e770f variable_watch: Check newValue for NULL
    cf4364c variable_watch: Don't share memory for callbacks
    6379d72 variable_watch: Fix a typo in the error message
    9df9825 variable_watch: Prevent making extra entries in the watch map
    f92f3ff variable_watch: Allow specifying the data to match in RemoveWatch
    faad4e1 variable_watch: Match client_data when finding duplicates
    8c0a98e variable_watch: Add a deleter for the client data
    dc1c654 variable_watch: Store client data as pointers
    8d1fc6c variable_watch: Add test for watching a variable multiple times


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=56e770fa9288a5801322f36442483e96cffc8a61
commit 56e770fa9288a5801322f36442483e96cffc8a61
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Tue Aug 6 14:32:19 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:31 2013 -0400

    variable_watch: Check newValue for NULL
    
    On read access, newValue can be NULL since there is no new value, so use
    the empty string instead.

diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 3b75ade..4eff19e 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -80,7 +80,7 @@ static void cmVariableWatchCommandVariableAccessed(
     {
     cmOStringStream msg;
     msg << "Variable \"" << variable.c_str() << "\" was accessed using "
-        << accessString << " with value \"" << newValue << "\".";
+        << accessString << " with value \"" << (newValue?newValue:"") << "\".";
     makefile->IssueMessage(cmake::LOG, msg.str());
     }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf4364cbb2e8640c50c30ab2267ef0c685dd4af9
commit cf4364cbb2e8640c50c30ab2267ef0c685dd4af9
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Fri Aug 2 15:41:45 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:31 2013 -0400

    variable_watch: Don't share memory for callbacks
    
    The command itself is owned by the cmMakefile class, but the
    cmVariableWatch which holds a pointer to the cmVariableWatchCommand via
    the client_data for the callback outlives the cmMakefile class in the Qt
    GUI. This means that when the cmMakefile is destroyed, the variable
    watch is still in effect, but with a stale pointer.
    
    To fix this, each callback is now a separate entity completely and
    doesn't rely on the command which spawned it at all.
    
    An example CMakeLists.txt which demonstrates the issue (only displayed
    in cmake-gui, so no tests can be written for it):
    
        set(var 0)
        variable_watch(var)

diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 2b81d79..3b75ade 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -14,63 +14,27 @@
 #include "cmVariableWatch.h"
 
 //----------------------------------------------------------------------------
-static void cmVariableWatchCommandVariableAccessed(
-  const std::string& variable, int access_type, void* client_data,
-  const char* newValue, const cmMakefile* mf)
+struct cmVariableWatchCallbackData
 {
-  cmVariableWatchCommand* command
-    = static_cast<cmVariableWatchCommand*>(client_data);
-  command->VariableAccessed(variable, access_type, newValue, mf);
-}
+  bool InCallback;
+  std::string Command;
+};
 
 //----------------------------------------------------------------------------
-cmVariableWatchCommand::cmVariableWatchCommand()
+static void cmVariableWatchCommandVariableAccessed(
+  const std::string& variable, int access_type, void* client_data,
+  const char* newValue, const cmMakefile* mf)
 {
-  this->InCallback = false;
-}
+  cmVariableWatchCallbackData* data
+    = static_cast<cmVariableWatchCallbackData*>(client_data);
 
-//----------------------------------------------------------------------------
-bool cmVariableWatchCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
-{
-  if ( args.size() < 1 )
-    {
-    this->SetError("must be called with at least one argument.");
-    return false;
-    }
-  std::string variable = args[0];
-  if ( args.size() > 1 )
-    {
-    std::string command = args[1];
-    this->Handlers[variable].Commands.push_back(args[1]);
-    }
-  if ( variable == "CMAKE_CURRENT_LIST_FILE" )
-    {
-    cmOStringStream ostr;
-    ostr << "cannot be set on the variable: " << variable.c_str();
-    this->SetError(ostr.str().c_str());
-    return false;
-    }
-
-  this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
-    variable, cmVariableWatchCommandVariableAccessed, this);
-
-  return true;
-}
-
-//----------------------------------------------------------------------------
-void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
-  int access_type, const char* newValue, const cmMakefile* mf)
-{
-  if ( this->InCallback )
+  if ( data->InCallback )
     {
     return;
     }
-  this->InCallback = true;
+  data->InCallback = true;
 
   cmListFileFunction newLFF;
-  cmVariableWatchCommandHandler *handler = &this->Handlers[variable];
-  cmVariableWatchCommandHandler::VectorOfCommands::iterator it;
   cmListFileArgument arg;
   bool processed = false;
   const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
@@ -80,10 +44,8 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
   cmMakefile* makefile = const_cast<cmMakefile*>(mf);
 
   std::string stack = makefile->GetProperty("LISTFILE_STACK");
-  for ( it = handler->Commands.begin(); it != handler->Commands.end();
-    ++ it )
+  if ( !data->Command.empty() )
     {
-    std::string command = *it;
     newLFF.Arguments.clear();
     newLFF.Arguments.push_back(
       cmListFileArgument(variable, true, "unknown", 9999));
@@ -95,7 +57,7 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
       cmListFileArgument(currentListFile, true, "unknown", 9999));
     newLFF.Arguments.push_back(
       cmListFileArgument(stack, true, "unknown", 9999));
-    newLFF.Name = command;
+    newLFF.Name = data->Command;
     newLFF.FilePath = "Some weird path";
     newLFF.Line = 9999;
     cmExecutionStatus status;
@@ -107,9 +69,9 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
       error << "Error in cmake code at\n"
         << arg.FilePath << ":" << arg.Line << ":\n"
         << "A command failed during the invocation of callback \""
-        << command << "\".";
+        << data->Command << "\".";
       cmSystemTools::Error(error.str().c_str());
-      this->InCallback = false;
+      data->InCallback = false;
       return;
       }
     processed = true;
@@ -121,5 +83,72 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
         << accessString << " with value \"" << newValue << "\".";
     makefile->IssueMessage(cmake::LOG, msg.str());
     }
-  this->InCallback = false;
+
+  data->InCallback = false;
+}
+
+//----------------------------------------------------------------------------
+static void deleteVariableWatchCallbackData(void* client_data)
+{
+  cmVariableWatchCallbackData* data
+    = static_cast<cmVariableWatchCallbackData*>(client_data);
+  delete data;
+}
+
+//----------------------------------------------------------------------------
+cmVariableWatchCommand::cmVariableWatchCommand()
+{
+}
+
+//----------------------------------------------------------------------------
+cmVariableWatchCommand::~cmVariableWatchCommand()
+{
+  std::set<std::string>::const_iterator it;
+  for ( it = this->WatchedVariables.begin();
+        it != this->WatchedVariables.end();
+        ++it )
+    {
+    this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
+      *it, cmVariableWatchCommandVariableAccessed);
+    }
+}
+
+//----------------------------------------------------------------------------
+bool cmVariableWatchCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+  if ( args.size() < 1 )
+    {
+    this->SetError("must be called with at least one argument.");
+    return false;
+    }
+  std::string variable = args[0];
+  std::string command;
+  if ( args.size() > 1 )
+    {
+    command = args[1];
+    }
+  if ( variable == "CMAKE_CURRENT_LIST_FILE" )
+    {
+    cmOStringStream ostr;
+    ostr << "cannot be set on the variable: " << variable.c_str();
+    this->SetError(ostr.str().c_str());
+    return false;
+    }
+
+  cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
+
+  data->InCallback = false;
+  data->Command = command;
+
+  this->WatchedVariables.insert(variable);
+  if ( !this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
+          variable, cmVariableWatchCommandVariableAccessed,
+          data, deleteVariableWatchCallbackData) )
+    {
+    deleteVariableWatchCallbackData(data);
+    return false;
+    }
+
+  return true;
 }
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 3abc088..545535c 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -14,13 +14,6 @@
 
 #include "cmCommand.h"
 
-class cmVariableWatchCommandHandler
-{
-public:
-  typedef std::vector<std::string> VectorOfCommands;
-  VectorOfCommands Commands;
-};
-
 /** \class cmVariableWatchCommand
  * \brief Watch when the variable changes and invoke command
  *
@@ -39,6 +32,9 @@ public:
   //! Default constructor
   cmVariableWatchCommand();
 
+  //! Destructor.
+  ~cmVariableWatchCommand();
+
   /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
@@ -83,13 +79,8 @@ public:
 
   cmTypeMacro(cmVariableWatchCommand, cmCommand);
 
-  void VariableAccessed(const std::string& variable, int access_type,
-    const char* newValue, const cmMakefile* mf);
-
 protected:
-  std::map<std::string, cmVariableWatchCommandHandler> Handlers;
-
-  bool InCallback;
+  std::set<std::string> WatchedVariables;
 };
 
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6379d729a2b19a2d8391ca7cf39008372aaf0a71
commit 6379d729a2b19a2d8391ca7cf39008372aaf0a71
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Fri Aug 2 15:49:50 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:31 2013 -0400

    variable_watch: Fix a typo in the error message
    
    There was no space between "callback" and the quoted command name.

diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 297a92b..2b81d79 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -106,7 +106,7 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
       cmOStringStream error;
       error << "Error in cmake code at\n"
         << arg.FilePath << ":" << arg.Line << ":\n"
-        << "A command failed during the invocation of callback\""
+        << "A command failed during the invocation of callback \""
         << command << "\".";
       cmSystemTools::Error(error.str().c_str());
       this->InCallback = false;

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9df982572ca2c3f22e3625f204b8e5c155d4f3d6
commit 9df982572ca2c3f22e3625f204b8e5c155d4f3d6
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Fri Aug 2 15:49:28 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:31 2013 -0400

    variable_watch: Prevent making extra entries in the watch map
    
    When removing a watch on a variable, using the operator [] on the
    internal map will create an empty watch if the variable doesn't have any
    existing watches. Rather than creating this empty structure in the map,
    return if there isn't a watch on the variable already.

diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index fbc446e..57eabe6 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -80,6 +80,10 @@ void cmVariableWatch::RemoveWatch(const std::string& variable,
                                   WatchMethod method,
                                   void* client_data /*=0*/)
 {
+  if ( !this->WatchMap.count(variable) )
+    {
+    return;
+    }
   cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
   cmVariableWatch::VectorOfPairs::iterator it;
   for ( it = vp->begin(); it != vp->end(); ++it )

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f92f3ffc7648de08005600f14465433cfba84bbc
commit f92f3ffc7648de08005600f14465433cfba84bbc
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Tue Aug 6 14:12:54 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:30 2013 -0400

    variable_watch: Allow specifying the data to match in RemoveWatch
    
    Now that watches are dependent on their client_data when adding, it also
    makes sense to allow matching the data for removal.

diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 4eb9cb3..fbc446e 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -77,13 +77,17 @@ bool cmVariableWatch::AddWatch(const std::string& variable,
 }
 
 void cmVariableWatch::RemoveWatch(const std::string& variable,
-                                  WatchMethod method)
+                                  WatchMethod method,
+                                  void* client_data /*=0*/)
 {
   cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
   cmVariableWatch::VectorOfPairs::iterator it;
   for ( it = vp->begin(); it != vp->end(); ++it )
     {
-    if ( (*it)->Method == method )
+    if ( (*it)->Method == method &&
+         // If client_data is NULL, we want to disconnect all watches against
+         // the given method; otherwise match ClientData as well.
+         (!client_data || (client_data == (*it)->ClientData)))
       {
       vp->erase(it);
       return;
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 3b6cafd..790c75a 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -36,7 +36,8 @@ public:
    */
   bool AddWatch(const std::string& variable, WatchMethod method,
                 void* client_data=0, DeleteData delete_data=0);
-  void RemoveWatch(const std::string& variable, WatchMethod method);
+  void RemoveWatch(const std::string& variable, WatchMethod method,
+                   void* client_data=0);
 
   /**
    * This method is called when variable is accessed

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=faad4e183d81e0ed5c6e1ae64ac23db95837ef71
commit faad4e183d81e0ed5c6e1ae64ac23db95837ef71
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Tue Aug 6 14:08:57 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:30 2013 -0400

    variable_watch: Match client_data when finding duplicates
    
    If a callback has the same data as another call, we don't want to delete
    the old callback. This is because if the client_data is the same, it
    might get deleted causing the new client_data to be bogus. Now, AddWatch
    will return true if it will use the watch, false otherwise. Callers
    should check the return value to know whether client_data was adopted by
    the watch or not.

diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 9a199ff..4eb9cb3 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -52,7 +52,7 @@ cmVariableWatch::~cmVariableWatch()
     }
 }
 
-void cmVariableWatch::AddWatch(const std::string& variable,
+bool cmVariableWatch::AddWatch(const std::string& variable,
                                WatchMethod method, void* client_data /*=0*/,
                                DeleteData delete_data /*=0*/)
 {
@@ -65,14 +65,15 @@ void cmVariableWatch::AddWatch(const std::string& variable,
   for ( cc = 0; cc < vp->size(); cc ++ )
     {
     cmVariableWatch::Pair* pair = (*vp)[cc];
-    if ( pair->Method == method )
+    if ( pair->Method == method &&
+         client_data && client_data == pair->ClientData)
       {
-      delete pair;
-      (*vp)[cc] = p;
-      return;
+      // Callback already exists
+      return false;
       }
     }
   vp->push_back(p);
+  return true;
 }
 
 void cmVariableWatch::RemoveWatch(const std::string& variable,
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index d666815..3b6cafd 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -34,7 +34,7 @@ public:
   /**
    * Add watch to the variable
    */
-  void AddWatch(const std::string& variable, WatchMethod method,
+  bool AddWatch(const std::string& variable, WatchMethod method,
                 void* client_data=0, DeleteData delete_data=0);
   void RemoveWatch(const std::string& variable, WatchMethod method);
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8c0a98e0dabb9fab5fa31a8b9aac2f8191ba46ed
commit 8c0a98e0dabb9fab5fa31a8b9aac2f8191ba46ed
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Fri Aug 2 15:44:15 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:30 2013 -0400

    variable_watch: Add a deleter for the client data
    
    The client data is arbitrary and the callback may be called an
    unspecified number of times, so the cmVariableWatch must be the one to
    delete the client data in the end (if it is needed at all).

diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 9b72df6..9a199ff 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -53,11 +53,13 @@ cmVariableWatch::~cmVariableWatch()
 }
 
 void cmVariableWatch::AddWatch(const std::string& variable,
-                               WatchMethod method, void* client_data /*=0*/)
+                               WatchMethod method, void* client_data /*=0*/,
+                               DeleteData delete_data /*=0*/)
 {
   cmVariableWatch::Pair* p = new cmVariableWatch::Pair;
   p->Method = method;
   p->ClientData = client_data;
+  p->DeleteDataCall = delete_data;
   cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
   cmVariableWatch::VectorOfPairs::size_type cc;
   for ( cc = 0; cc < vp->size(); cc ++ )
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 45273e5..d666815 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -26,6 +26,7 @@ class cmVariableWatch
 public:
   typedef void (*WatchMethod)(const std::string& variable, int access_type,
     void* client_data, const char* newValue, const cmMakefile* mf);
+  typedef void (*DeleteData)(void* client_data);
 
   cmVariableWatch();
   ~cmVariableWatch();
@@ -34,7 +35,7 @@ public:
    * Add watch to the variable
    */
   void AddWatch(const std::string& variable, WatchMethod method,
-                void* client_data=0);
+                void* client_data=0, DeleteData delete_data=0);
   void RemoveWatch(const std::string& variable, WatchMethod method);
 
   /**
@@ -67,7 +68,15 @@ protected:
   {
     WatchMethod Method;
     void*        ClientData;
-    Pair() : Method(0), ClientData(0) {}
+    DeleteData   DeleteDataCall;
+    Pair() : Method(0), ClientData(0), DeleteDataCall(0) {}
+    ~Pair()
+      {
+      if (this->DeleteDataCall && this->ClientData)
+        {
+        this->DeleteDataCall(this->ClientData);
+        }
+      }
   };
 
   typedef std::vector< Pair* > VectorOfPairs;

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dc1c6546704bc277e7c884a53e538ee5d8b831c8
commit dc1c6546704bc277e7c884a53e538ee5d8b831c8
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Fri Aug 2 15:43:15 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:30 2013 -0400

    variable_watch: Store client data as pointers
    
    The STL containers create extra copies which makes keeping track of the
    owner of the client data much messier.

diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 3905e9b..9b72df6 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -37,21 +37,35 @@ cmVariableWatch::cmVariableWatch()
 
 cmVariableWatch::~cmVariableWatch()
 {
+  cmVariableWatch::StringToVectorOfPairs::iterator svp_it;
+
+  for ( svp_it = this->WatchMap.begin();
+        svp_it != this->WatchMap.end(); ++svp_it )
+    {
+    cmVariableWatch::VectorOfPairs::iterator p_it;
+
+    for ( p_it = svp_it->second.begin();
+          p_it != svp_it->second.end(); ++p_it )
+      {
+      delete *p_it;
+      }
+    }
 }
 
 void cmVariableWatch::AddWatch(const std::string& variable,
                                WatchMethod method, void* client_data /*=0*/)
 {
-  cmVariableWatch::Pair p;
-  p.Method = method;
-  p.ClientData = client_data;
+  cmVariableWatch::Pair* p = new cmVariableWatch::Pair;
+  p->Method = method;
+  p->ClientData = client_data;
   cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
   cmVariableWatch::VectorOfPairs::size_type cc;
   for ( cc = 0; cc < vp->size(); cc ++ )
     {
-    cmVariableWatch::Pair* pair = &(*vp)[cc];
+    cmVariableWatch::Pair* pair = (*vp)[cc];
     if ( pair->Method == method )
       {
+      delete pair;
       (*vp)[cc] = p;
       return;
       }
@@ -66,7 +80,7 @@ void cmVariableWatch::RemoveWatch(const std::string& variable,
   cmVariableWatch::VectorOfPairs::iterator it;
   for ( it = vp->begin(); it != vp->end(); ++it )
     {
-    if ( it->Method == method )
+    if ( (*it)->Method == method )
       {
       vp->erase(it);
       return;
@@ -87,7 +101,7 @@ void  cmVariableWatch::VariableAccessed(const std::string& variable,
     cmVariableWatch::VectorOfPairs::const_iterator it;
     for ( it = vp->begin(); it != vp->end(); it ++ )
       {
-      it->Method(variable, access_type, it->ClientData,
+      (*it)->Method(variable, access_type, (*it)->ClientData,
         newValue, mf);
       }
     }
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 7dd4ac5..45273e5 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -70,7 +70,7 @@ protected:
     Pair() : Method(0), ClientData(0) {}
   };
 
-  typedef std::vector< Pair > VectorOfPairs;
+  typedef std::vector< Pair* > VectorOfPairs;
   typedef std::map<cmStdString, VectorOfPairs > StringToVectorOfPairs;
 
   StringToVectorOfPairs WatchMap;

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8d1fc6c88946f6dd18c6f17d4f6f8825547972ef
commit 8d1fc6c88946f6dd18c6f17d4f6f8825547972ef
Author:     Ben Boeckel <mathstuf at gmail.com>
AuthorDate: Tue Aug 6 14:31:28 2013 -0400
Commit:     Ben Boeckel <mathstuf at gmail.com>
CommitDate: Tue Aug 6 15:35:23 2013 -0400

    variable_watch: Add test for watching a variable multiple times
    
    Currently, variable_watch will only use one callback (the last one
    used), but there's no reason that multiple watchers should not be
    allowed for a single variable.
    
    This test is fixed by this branch.

diff --git a/Tests/RunCMake/variable_watch/RunCMakeTest.cmake b/Tests/RunCMake/variable_watch/RunCMakeTest.cmake
index 8d20476..9becb4c 100644
--- a/Tests/RunCMake/variable_watch/RunCMakeTest.cmake
+++ b/Tests/RunCMake/variable_watch/RunCMakeTest.cmake
@@ -2,3 +2,4 @@ include(RunCMake)
 
 run_cmake(ModifiedAccess)
 run_cmake(NoWatcher)
+run_cmake(WatchTwice)
diff --git a/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt b/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt
new file mode 100644
index 0000000..fa7d347
--- /dev/null
+++ b/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt
@@ -0,0 +1,2 @@
+From watch1
+From watch2
diff --git a/Tests/RunCMake/variable_watch/WatchTwice.cmake b/Tests/RunCMake/variable_watch/WatchTwice.cmake
new file mode 100644
index 0000000..540cfc1
--- /dev/null
+++ b/Tests/RunCMake/variable_watch/WatchTwice.cmake
@@ -0,0 +1,11 @@
+function (watch1)
+    message("From watch1")
+endfunction ()
+
+function (watch2)
+    message("From watch2")
+endfunction ()
+
+variable_watch(watched watch1)
+variable_watch(watched watch2)
+set(access "${watched}")

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list