|
106 | 106 | * All operations between creating and destroying the transaction |
107 | 107 | * object are treated as performed in a transaction block and |
108 | 108 | * can be rolled back. |
109 | | - * The locks are held for the entire duration of the transaction. They |
110 | | - * are released at the end of the scope, so within the `catch` block, |
111 | | - * they are already unlocked. |
112 | 109 | * The best way to use manual transactions is by |
113 | 110 | * @ref pmem::obj::transaction::run, which is used in example above. |
114 | 111 | * |
|
117 | 114 | * performed in a transaction block and can be rolled back. |
118 | 115 | * If you have a C++17 compliant compiler, the automatic transaction will |
119 | 116 | * commit and abort automatically depending on the context of object's destruction. |
120 | | - * The locks are held for the entire duration of the transaction. They |
121 | | - * are released at the end of the scope, so within the `catch` block, |
| 117 | + * |
| 118 | + * In both approaches one of the parameters is the `locks`. They are held for the entire duration |
| 119 | + * of the transaction and they are released at the end of the scope - so within the `catch` block, |
122 | 120 | * they are already unlocked. |
123 | 121 | * |
124 | 122 | * If you want to read more and see example usages of both, you have to see |
|
191 | 189 | * take a look at description of each class to get the details of their behavior. |
192 | 190 | */ |
193 | 191 |
|
194 | | -/** @defgroup synchronization Synchronization Primitives*/ |
| 192 | +/** @defgroup synchronization Synchronization Primitives |
| 193 | + * Persistent memory resident implementation of synchronization primitives. |
| 194 | + * |
| 195 | + * In concurrent programming, we often require mechanisms for synchronizing access to shared resources. |
| 196 | + * Typically to solve such issues we use synchronization primitives like mutexes and condition variables. |
| 197 | + * As persistent memory offers bigger capacity than DRAM it may be useful to store synchronization primitives |
| 198 | + * on it. Unfortunately such approach may cause performance degradation due to frequent writes to a memory |
| 199 | + * with relatively higher latency (it's because taking a lock or signaling a conditional variable often |
| 200 | + * requires additional writes). Few extra words how locks can be used in libpmemobj-cpp can be found in |
| 201 | + * @ref transactions. |
| 202 | + * |
| 203 | + * It's worth noticing that pmem locks are automatically released on recovery or when crash happened. |
| 204 | + * |
| 205 | + * # Additional resources |
| 206 | + * - [Libpmemobj-cpp - lessons learned](https://pmem.io/blog/2021/09/libpmemobj-cpp-lessons-learned) |
| 207 | + * In this blog post we explain, i.a., why keeping locks on pmem is not a good idea. |
| 208 | + */ |
| 209 | + |
195 | 210 | /** @defgroup primitives Primitives |
196 | 211 | * Basic classes that provides PMEM-aware pointers and pool handlers. |
197 | 212 | * |
|
256 | 271 | * |
257 | 272 | * You should check every function you will use in context of possible |
258 | 273 | * exceptions and then handle them to avoid crash. |
259 | | - **/ |
| 274 | + */ |
0 commit comments