<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to ReadComputeWrite</title><link>https://sourceforge.net/p/madara/wiki/ReadComputeWrite/</link><description>Recent changes to ReadComputeWrite</description><atom:link href="https://sourceforge.net/p/madara/wiki/ReadComputeWrite/feed" rel="self"/><language>en</language><lastBuildDate>Tue, 28 Nov 2017 20:38:30 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/madara/wiki/ReadComputeWrite/feed" rel="self" type="application/rss+xml"/><item><title>ReadComputeWrite modified by David Kyle</title><link>https://sourceforge.net/p/madara/wiki/ReadComputeWrite/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v3
+++ v4
@@ -103,21 +103,21 @@
 class NewThread : public RCWThread {
 private:
   int x;
-  Tracked&amp;lt;int&amp;gt; tx;
+  Tracked&amp;lt;int&amp;gt; x2;
   Tracked&amp;lt;std::string&amp;gt; s;
   Tracked&amp;lt;std::vector&amp;lt;int64_t&amp;gt;&amp;gt; vec;
 public:
   void setup(Transaction &amp;amp;tx) override {
      tx.build("x", x).init(42).add()
-     tx = 17;
-     tx.add_init("tx", tx);
+     x2 = 17;
+     tx.add_init("x2", x2);
      tx.build("s", s).init("Hello World").add();
      tx.build("vec", vec).init({2, 3, 5, 7, 11, 13, 17}).add();
   }

   void compute(const Transaction &amp;amp;tx) override {
-    cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; tx &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; s &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; vec.size() &amp;lt;&amp;lt; endl;
-    ++x; --tx; s+= "!"; vec.push_back(0);
+    cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; x2 &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; s &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; vec.size() &amp;lt;&amp;lt; endl;
+    ++x; --x2; s+= "!"; vec.push_back(0);
   }

   void cleanup(Transaction &amp;amp;tx) override {
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">David Kyle</dc:creator><pubDate>Tue, 28 Nov 2017 20:38:30 -0000</pubDate><guid>https://sourceforge.net1b89a35e5a201984fc533469d7e019d938cef98b</guid></item><item><title>ReadComputeWrite modified by David Kyle</title><link>https://sourceforge.net/p/madara/wiki/ReadComputeWrite/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v2
+++ v3
@@ -13,6 +13,8 @@
     rcw::Transaction tr(kb);

 This will be the knowledge base that the `Transaction` reads from and updates. Note that the `Transaction` object can safely outlive the `KnowledgeBase` object passed to it; the underlying knowledge base will be kept alive as long as the `Transaction` is alive.
+
+For an example of usage, see **`tests/rcw/test_rcw_transaction.cpp`**.

 # `add()`

@@ -67,8 +69,8 @@

 The available configuration options are:

-`ro()`: Mapping will `pull()` into given variable, but not `push()`
-`wo()`: `pull()` doesn't read from the knowledge base, and instead sets the variable to its default value. `push()` works normally.
+`readonly()`/`ro()`: Mapping will `pull()` into given variable, but not `push()`
+`writeonly()`/`wo()`: `pull()` doesn't read from the knowledge base, and instead sets the variable to its default value. `push()` works normally.
 `init()`: Immediately (when `add()` is called) update the knowledge base with the current value of the variable.
 `init(value)`: Immediately (when called) set the variable to `value`; then when `add()` is called, update the knowledge base as with `init()`
 `prefix()`: The variable must be a `Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;`. Instead of storing the vector's contents as a native MADARA array, store it as multiple madara entries, one per element. The variable name is instead used as a prefix. The size of the array is stored in `$PREFIX.size`, while the elements are stored in `$PREFIX.0`, `$PREFIX.1`, etc.
@@ -80,11 +82,13 @@
 # Using `Tracked`
 By default, `Transaction` tracks whether a value has changed, and thus needs to be written back to the knowledge base, by keeping a copy of the original value as read during `pull()`, then checking if it has changed in `push()`. The `Tracked` template wraps arbitrary variable types, and provides its own tracking of modified state, eliminating that copy, and allowing you to treat a value as modified even if it hasn't actually changed.

-The `Tracked` template overloads most operators, allowing it to be used as if it were the wrapped type in most cases. However, to simply get the value, you must use the `*` operator (or the `get()` method), and to call methods or access member variables of the wrapped type you must use the `-&amp;gt;` operator. The latter, however, only supports `const` methods and reading member variables. To call non-`const` methods and change member variables, call the `get_mut()` method (which immediately marks the value as modified), and use the returned reference.
+The `Tracked` template overloads most operators, allowing it to be used as if it were the wrapped type in most cases. However, to simply get the value, you must use the `*` operator (or the `get()` method), and to call methods or access member variables of the wrapped type you must use the `-&amp;gt;` operator. The latter, however, only supports `const` methods and reading member variables. To call non-`const` methods and change member variables, call the `get_mut()` (or its synonym `get_mutable()`) method, which immediately marks the value as modified, and use the returned reference.

 There are two specializations of `Tracked` provided; one for `Tracked&amp;lt;std::string&amp;gt;` and `Tracked&amp;lt;std::vector&amp;gt;`. The former simply provides most `std::string` methods itself, allowing usage through the `.` operator, and allowing more accurate modification tracking than `get_mut()`.

 The latter also forwards most `std::vector` methods, but also provides additional tracking which makes `pull()`, and space usage, much more efficient than than the generic implementation would provide, or that `std::vector&amp;lt;Tracked&amp;lt;...&amp;gt;&amp;gt;` provides. With `Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;`, there is only a single bit of overhead for each element to track modification status. Without this specialization, there would, for example, likely be an 8-byte overhead per element on 64-bit systems.
+
+For an example of usage, see **`tests/rcw/test_rcw_tracked.cpp`**.

 # Using `RCWThread`
 The `RCWThread` class provides an easy way to implement a thread with Read-Compute-Write semantics. It handles creating and managing a `Transaction` for you. Much like `BaseThread`, you have three (albeit differently named) virtual member functions to override:
@@ -124,6 +128,8 @@

 During `compute()`, you can call `add()`/`build()` (except with `_init`/`init()`) and `remove()`. If you add a new variable, it won't get updated (with `pull()`) until the next time `compute()` is called.

+For an example of usage, see **`tests/rcw/test_rcw_prodcon.cpp`**.
+
 # Adding Custom Types to a `Transaction`
 By default, you can add variables that are:

@@ -149,3 +155,5 @@
 * `void clear_dirty(Type &amp;amp;o)`: clear the modification status

 If you implement the above, `Transaction` will use your type as if it were `Tracked&amp;lt;...&amp;gt;`.
+
+For an example of usage, see **`tests/rcw/test_rcw_custom.cpp`**.
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">David Kyle</dc:creator><pubDate>Fri, 13 Oct 2017 17:05:39 -0000</pubDate><guid>https://sourceforge.netea8688e3f24baf4fdb5ef1925f98c8adc0c4cd1a</guid></item><item><title>ReadComputeWrite modified by David Kyle</title><link>https://sourceforge.net/p/madara/wiki/ReadComputeWrite/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v1
+++ v2
@@ -34,7 +34,7 @@

 ## `push()` and `pull()`

-Unlike MADARA containers, variables added to a transaction do not automatically read and write an entry in the knowledge base. Instead, the `Transaction` provides two methods, `push()` and  `pull()`, to write and read, respectively, the values in the knowledge base. If you are using an `RCWThread`, do not call `push()` or `pull()` directly. The thread object will handle that for you.
+Unlike MADARA containers, variables added to a transaction do not automatically read and write an entry in the knowledge base. Instead, the `Transaction` provides two methods, `push()` and  `pull()`, to write and read, respectively, the values in the knowledge base. If you are using an `RCWThread`, you need not call `push()` or `pull()` directly. The thread object will handle that for you.

 For example, if using a `Transaction` directly:

@@ -73,14 +73,18 @@
 `init(value)`: Immediately (when called) set the variable to `value`; then when `add()` is called, update the knowledge base as with `init()`
 `prefix()`: The variable must be a `Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;`. Instead of storing the vector's contents as a native MADARA array, store it as multiple madara entries, one per element. The variable name is instead used as a prefix. The size of the array is stored in `$PREFIX.size`, while the elements are stored in `$PREFIX.0`, `$PREFIX.1`, etc.

+## `const Transaction` Objects
+
+The `const`-ness of a `Transaction` refers to access to its underlying knowledge base, not the object itself. Therefore, a `const Transaction` can have variables added or removed, but cannot `push()`, `pull()`, or use the `_init` forms of `add()`. This is especially useful for `RCWThread`, where the `compute()` method takes a `const Transaction &amp;amp;`, and thus prevents accidentally breaking the read-comput-write pattern in that method.
+
 # Using `Tracked`
 By default, `Transaction` tracks whether a value has changed, and thus needs to be written back to the knowledge base, by keeping a copy of the original value as read during `pull()`, then checking if it has changed in `push()`. The `Tracked` template wraps arbitrary variable types, and provides its own tracking of modified state, eliminating that copy, and allowing you to treat a value as modified even if it hasn't actually changed.

 The `Tracked` template overloads most operators, allowing it to be used as if it were the wrapped type in most cases. However, to simply get the value, you must use the `*` operator (or the `get()` method), and to call methods or access member variables of the wrapped type you must use the `-&amp;gt;` operator. The latter, however, only supports `const` methods and reading member variables. To call non-`const` methods and change member variables, call the `get_mut()` method (which immediately marks the value as modified), and use the returned reference.

-There are two specializations of `Tracked` provided; one for `Tracked&amp;lt;std::string&amp;gt;` and `Tracked&amp;lt;std::vector&amp;gt;`. The former simply provides most of the `std::string` methods itself, allowing usage through the `.` operator, and allowing more accurate modification tracking than `get_mut()`.
+There are two specializations of `Tracked` provided; one for `Tracked&amp;lt;std::string&amp;gt;` and `Tracked&amp;lt;std::vector&amp;gt;`. The former simply provides most `std::string` methods itself, allowing usage through the `.` operator, and allowing more accurate modification tracking than `get_mut()`.

-The latter also forwards most of `std::vector` methods, but also provides additional tracking which makes `pull()`, and space usage, much more efficient than than the generic implementation would provide, or that `std::vector&amp;lt;Tracked&amp;lt;...&amp;gt;&amp;gt;` provides. With `Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;`, there is only a single bit of overhead for each element to track modification status. Without this specialization, there would generally be an 8-byte overhead per element on 64-bit systems.
+The latter also forwards most `std::vector` methods, but also provides additional tracking which makes `pull()`, and space usage, much more efficient than than the generic implementation would provide, or that `std::vector&amp;lt;Tracked&amp;lt;...&amp;gt;&amp;gt;` provides. With `Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;`, there is only a single bit of overhead for each element to track modification status. Without this specialization, there would, for example, likely be an 8-byte overhead per element on 64-bit systems.

 # Using `RCWThread`
 The `RCWThread` class provides an easy way to implement a thread with Read-Compute-Write semantics. It handles creating and managing a `Transaction` for you. Much like `BaseThread`, you have three (albeit differently named) virtual member functions to override:
@@ -89,6 +93,59 @@
 * `compute()`, which operates on your variables, and
 * `cleanup()`, optionally, to handle termination of the thread.

-Ensure you do not call `push()`, `pull()`, or an `add()` or `build()` which initializes a variable in the knowledge base. These break the RCW pattern, and can produce unexpected results.
+As a simple example of an `RCWThread`:

-It is, however, OK to call `add()`/`build()` and `remove()` otherwise. Note that if you add a new variable, it won't get updated until the next time `compute()` is called.
+~~~
+class NewThread : public RCWThread {
+private:
+  int x;
+  Tracked&amp;lt;int&amp;gt; tx;
+  Tracked&amp;lt;std::string&amp;gt; s;
+  Tracked&amp;lt;std::vector&amp;lt;int64_t&amp;gt;&amp;gt; vec;
+public:
+  void setup(Transaction &amp;amp;tx) override {
+     tx.build("x", x).init(42).add()
+     tx = 17;
+     tx.add_init("tx", tx);
+     tx.build("s", s).init("Hello World").add();
+     tx.build("vec", vec).init({2, 3, 5, 7, 11, 13, 17}).add();
+  }
+  
+  void compute(const Transaction &amp;amp;tx) override {
+    cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; tx &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; s &amp;lt;&amp;lt; " " &amp;lt;&amp;lt; vec.size() &amp;lt;&amp;lt; endl;
+    ++x; --tx; s+= "!"; vec.push_back(0);
+  }
+  
+  void cleanup(Transaction &amp;amp;tx) override {
+      // Not needed for this example
+  }
+};
+~~~
+
+During `compute()`, you can call `add()`/`build()` (except with `_init`/`init()`) and `remove()`. If you add a new variable, it won't get updated (with `pull()`) until the next time `compute()` is called.
+
+# Adding Custom Types to a `Transaction`
+By default, you can add variables that are:
+
+* any primitive type
+* `std::string`
+* `std::vector&amp;lt;int64_t&amp;gt;` or `std::vector&amp;lt;double&amp;gt;`
+* `madara::knowledge::KnowledgeRecord`
+
+If you add using the `prefix()` build option, you can add any std::vector&amp;lt;T&amp;gt;, where T is itself supported in a non-`prefix()` mapping.
+
+You can extend support to new types by implementing a set of functions in the same namespace as the type itself (or in `madara::knowledge::rcw`, but the former is preferred).
+
+For the most basic support, implement these functions, where `Type` is the name of your type, and `Basic` is one of the above default supported types:
+
+* `Basic get_value(const Type &amp;amp;o)`: given some object of your `Type`, return one of the default supported types.
+* `set_value(Type &amp;amp;o, const Basic &amp;amp;i)`: given the value, set the object of your `Type` accordingly
+
+With this basic support, your can add your type directly (in which case a copy will be kept with every `pull()` for later comparison), or within `Tracked&amp;lt;...&amp;gt;`.
+
+If your type tracks its own modification status,  you can also implement the following:
+
+* `bool is_dirty(const Type &amp;amp;o)`: return `true` if `o` has been modified; `false` if not
+* `void clear_dirty(Type &amp;amp;o)`: clear the modification status
+
+If you implement the above, `Transaction` will use your type as if it were `Tracked&amp;lt;...&amp;gt;`.
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">David Kyle</dc:creator><pubDate>Tue, 10 Oct 2017 14:11:42 -0000</pubDate><guid>https://sourceforge.net71568f64296f6ba89e3dbc9a0efdec4b0bc95522</guid></item><item><title>ReadComputeWrite modified by David Kyle</title><link>https://sourceforge.net/p/madara/wiki/ReadComputeWrite/</link><description>&lt;div class="markdown_content"&gt;&lt;p&gt;One way to simplify reasoning about parallel tasks is to confine them to a Read-Compute-Write cycle; i.e., all information in the shared knowledge base is read at once, then computed upon (without accessing any shared state), then written back. This allows the compute phase to avoid any locking, the read and write phases can hold the knowledge base lock for as short of time as possible.&lt;/p&gt;
&lt;p&gt;To support this pattern, MADARA offers a &lt;code&gt;Transaction&lt;/code&gt; class. This class handles reading from the knowledge base into variables of your choosing, and writing them back, if they have changed. MADARA also provides a &lt;code&gt;Tracked&lt;/code&gt; template, which when applied to a type, provides a type which tracks is "dirty" status, i.e., whether it has been modified.&lt;/p&gt;
&lt;p&gt;Finally, MADARA also provides an &lt;code&gt;RCWThread&lt;/code&gt; which extends &lt;code&gt;BaseThread&lt;/code&gt; and allows a thread to easily fit the Read-Compute-Write pattern.&lt;/p&gt;
&lt;h1 id="using-transaction"&gt;Using &lt;code&gt;Transaction&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;If you are using an &lt;code&gt;RCWThread&lt;/code&gt;, it will create a &lt;code&gt;Transaction&lt;/code&gt; for you; you should not create one yourself. Otherwise, to create a &lt;code&gt;Transaction&lt;/code&gt;, simply construct it with a KnowledgeBase:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;madara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;knowledge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;KnowledgeBase&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;rcw&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt; &lt;span class="n"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will be the knowledge base that the &lt;code&gt;Transaction&lt;/code&gt; reads from and updates. Note that the &lt;code&gt;Transaction&lt;/code&gt; object can safely outlive the &lt;code&gt;KnowledgeBase&lt;/code&gt; object passed to it; the underlying knowledge base will be kept alive as long as the &lt;code&gt;Transaction&lt;/code&gt; is alive.&lt;/p&gt;
&lt;h1 id="add"&gt;&lt;code&gt;add()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Next, you should initialize the &lt;code&gt;Transaction&lt;/code&gt; by adding variables to it:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;int&lt;/span&gt; &lt;span class="nt"&gt;x&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"my.x"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;x&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;double&lt;/span&gt; &lt;span class="nt"&gt;y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"my.y"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;y&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;string&lt;/span&gt; &lt;span class="nt"&gt;s&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"my.s"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;s&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The string given is the name of the MADARA variable. It can be any legal MADARA key, and need not have any relationship with the variable given. If it does not exist, it will be created immediately with the default &lt;code&gt;0&lt;/code&gt; value. If it already exists, the value will not be touched. Any current value of the second parameter is ignored. The second parameter will have its address taken and stored. Ensure the given object lives long enough. If an object added to a &lt;code&gt;Transaction&lt;/code&gt; is destructed, it is undefined behavior to do anything with that &lt;code&gt;Transaction&lt;/code&gt; object except destruct it.&lt;/p&gt;
&lt;p&gt;If you wish the initialize the corresponding entry in the MADARA knowledge base, use the &lt;code&gt;add_init()&lt;/code&gt; method instead:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;int z = 42;
tr.add_init("my.z", z);
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="push-and-pull"&gt;&lt;code&gt;push()&lt;/code&gt; and &lt;code&gt;pull()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Unlike MADARA containers, variables added to a transaction do not automatically read and write an entry in the knowledge base. Instead, the &lt;code&gt;Transaction&lt;/code&gt; provides two methods, &lt;code&gt;push()&lt;/code&gt; and  &lt;code&gt;pull()&lt;/code&gt;, to write and read, respectively, the values in the knowledge base. If you are using an &lt;code&gt;RCWThread&lt;/code&gt;, do not call &lt;code&gt;push()&lt;/code&gt; or &lt;code&gt;pull()&lt;/code&gt; directly. The thread object will handle that for you.&lt;/p&gt;
&lt;p&gt;For example, if using a &lt;code&gt;Transaction&lt;/code&gt; directly:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;9&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;" \""&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"\""&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;endl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;/* Output: 9 0 42 "0" */&lt;/span&gt;
&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;pull&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;" \""&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"\""&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;endl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;/* Output: 0 0 42 "0" */&lt;/span&gt;
&lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;13&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"my.x"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;to_integer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;endl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Output: 0 */&lt;/span&gt;
&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;push&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"my.x"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;to_integer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;endl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Output: 13 */&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="remove"&gt;&lt;code&gt;remove()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;After adding a variable to a &lt;code&gt;Transaction&lt;/code&gt;, you can remove it with the &lt;code&gt;remove()&lt;/code&gt; method. You can pass either the string name of MADARA entry, or a pointer to the variable you originally added.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;tr.remove(&amp;amp;x);
tr.remove("my.y");
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="build"&gt;&lt;code&gt;build()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;build()&lt;/code&gt; method provides a means for greater control of how added variables are handled by a &lt;code&gt;Transaction&lt;/code&gt;. The &lt;code&gt;add()&lt;/code&gt; and various &lt;code&gt;add_*()&lt;/code&gt; methods are simply shorthand for the more fully feature &lt;code&gt;build()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;When you call &lt;code&gt;build()&lt;/code&gt; on a transaction (with the same arguments as &lt;code&gt;add()&lt;/code&gt;), it returns a &lt;code&gt;Transaction::Builder&lt;/code&gt; object, which provides several methods for customizing options. Each of these methods returns the builder object itself, so you can chain these methods. To actually add the variable to the &lt;code&gt;Transaction&lt;/code&gt;, call the &lt;code&gt;add()&lt;/code&gt; method on the builder object. For example, to add a write-only variable that will be initialized with a given value immediately:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;int b;
tr.build("my.b", b).wo().init(7).add();
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The available configuration options are:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ro()&lt;/code&gt;: Mapping will &lt;code&gt;pull()&lt;/code&gt; into given variable, but not &lt;code&gt;push()&lt;/code&gt;&lt;br/&gt;
&lt;code&gt;wo()&lt;/code&gt;: &lt;code&gt;pull()&lt;/code&gt; doesn't read from the knowledge base, and instead sets the variable to its default value. &lt;code&gt;push()&lt;/code&gt; works normally.&lt;br/&gt;
&lt;code&gt;init()&lt;/code&gt;: Immediately (when &lt;code&gt;add()&lt;/code&gt; is called) update the knowledge base with the current value of the variable.&lt;br/&gt;
&lt;code&gt;init(value)&lt;/code&gt;: Immediately (when called) set the variable to &lt;code&gt;value&lt;/code&gt;; then when &lt;code&gt;add()&lt;/code&gt; is called, update the knowledge base as with &lt;code&gt;init()&lt;/code&gt;&lt;br/&gt;
&lt;code&gt;prefix()&lt;/code&gt;: The variable must be a &lt;code&gt;Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;&lt;/code&gt;. Instead of storing the vector's contents as a native MADARA array, store it as multiple madara entries, one per element. The variable name is instead used as a prefix. The size of the array is stored in &lt;code&gt;$PREFIX.size&lt;/code&gt;, while the elements are stored in &lt;code&gt;$PREFIX.0&lt;/code&gt;, &lt;code&gt;$PREFIX.1&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h1 id="using-tracked"&gt;Using &lt;code&gt;Tracked&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;By default, &lt;code&gt;Transaction&lt;/code&gt; tracks whether a value has changed, and thus needs to be written back to the knowledge base, by keeping a copy of the original value as read during &lt;code&gt;pull()&lt;/code&gt;, then checking if it has changed in &lt;code&gt;push()&lt;/code&gt;. The &lt;code&gt;Tracked&lt;/code&gt; template wraps arbitrary variable types, and provides its own tracking of modified state, eliminating that copy, and allowing you to treat a value as modified even if it hasn't actually changed.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Tracked&lt;/code&gt; template overloads most operators, allowing it to be used as if it were the wrapped type in most cases. However, to simply get the value, you must use the &lt;code&gt;*&lt;/code&gt; operator (or the &lt;code&gt;get()&lt;/code&gt; method), and to call methods or access member variables of the wrapped type you must use the &lt;code&gt;-&amp;gt;&lt;/code&gt; operator. The latter, however, only supports &lt;code&gt;const&lt;/code&gt; methods and reading member variables. To call non-&lt;code&gt;const&lt;/code&gt; methods and change member variables, call the &lt;code&gt;get_mut()&lt;/code&gt; method (which immediately marks the value as modified), and use the returned reference.&lt;/p&gt;
&lt;p&gt;There are two specializations of &lt;code&gt;Tracked&lt;/code&gt; provided; one for &lt;code&gt;Tracked&amp;lt;std::string&amp;gt;&lt;/code&gt; and &lt;code&gt;Tracked&amp;lt;std::vector&amp;gt;&lt;/code&gt;. The former simply provides most of the &lt;code&gt;std::string&lt;/code&gt; methods itself, allowing usage through the &lt;code&gt;.&lt;/code&gt; operator, and allowing more accurate modification tracking than &lt;code&gt;get_mut()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The latter also forwards most of &lt;code&gt;std::vector&lt;/code&gt; methods, but also provides additional tracking which makes &lt;code&gt;pull()&lt;/code&gt;, and space usage, much more efficient than than the generic implementation would provide, or that &lt;code&gt;std::vector&amp;lt;Tracked&amp;lt;...&amp;gt;&amp;gt;&lt;/code&gt; provides. With &lt;code&gt;Tracked&amp;lt;std::vector&amp;lt;...&amp;gt;&amp;gt;&lt;/code&gt;, there is only a single bit of overhead for each element to track modification status. Without this specialization, there would generally be an 8-byte overhead per element on 64-bit systems.&lt;/p&gt;
&lt;h1 id="using-rcwthread"&gt;Using &lt;code&gt;RCWThread&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;RCWThread&lt;/code&gt; class provides an easy way to implement a thread with Read-Compute-Write semantics. It handles creating and managing a &lt;code&gt;Transaction&lt;/code&gt; for you. Much like &lt;code&gt;BaseThread&lt;/code&gt;, you have three (albeit differently named) virtual member functions to override:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;setup()&lt;/code&gt;, in which you should &lt;code&gt;add()&lt;/code&gt; your variables (typically member variables of your thread class inheriting from &lt;code&gt;RCWThread&lt;/code&gt;) to the &lt;code&gt;Transaction&lt;/code&gt; passed into it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compute()&lt;/code&gt;, which operates on your variables, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cleanup()&lt;/code&gt;, optionally, to handle termination of the thread.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ensure you do not call &lt;code&gt;push()&lt;/code&gt;, &lt;code&gt;pull()&lt;/code&gt;, or an &lt;code&gt;add()&lt;/code&gt; or &lt;code&gt;build()&lt;/code&gt; which initializes a variable in the knowledge base. These break the RCW pattern, and can produce unexpected results.&lt;/p&gt;
&lt;p&gt;It is, however, OK to call &lt;code&gt;add()&lt;/code&gt;/&lt;code&gt;build()&lt;/code&gt; and &lt;code&gt;remove()&lt;/code&gt; otherwise. Note that if you add a new variable, it won't get updated until the next time &lt;code&gt;compute()&lt;/code&gt; is called.&lt;/p&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">David Kyle</dc:creator><pubDate>Mon, 09 Oct 2017 21:40:33 -0000</pubDate><guid>https://sourceforge.netc7a405af4cb7fec13ec6c55055e9738f6ae946c7</guid></item></channel></rss>