When not to use RAII for resource management

Could someone provide me with one or more specific examples in which RAII was not the most efficient resource management method and why?

+6
c ++ design raii
source share
5 answers

The only time I can think about where RAII was not a solution is multi-threaded blocking a critical region. In general, it is advisable to obtain a critical region lock (think about this resource) and hold it in the RAII object:

void push( Element e ) { lock l(queue_mutex); // acquire on constructing, release on destructing queue.push(e); } 

But there are situations when you cannot use RAII for this purpose. In particular, if the variable used in the loop state is shared by several threads, and you cannot hold the lock for the whole loop, then you must acquire and release the lock using another mechanism:

 void stop_thread() { lock l(control_mutex); exit = true; } void run() { control_mutex.acquire(); while ( !exit ) { // exit is a boolean modified somewhere else control_mutex.release(); // do work control_mutex.acquire(); } control_mutex.release(); } 

Perhaps even now you can use RAII with (ab) using operator, which I think of, but I never thought about that. But I think this is not so natural:

 void run() { while ( lock(control_mutex), !exit ) { // do work } } 

So, I think the answer is that I cannot imagine ...

EDIT: Other solutions for the same problem using RAII:

@ Mark Ransom :

 bool should_exit() const { lock l(mutex); return exit; } void run() { while ( !should_exit() ) { // do work } } 

@ fnieto :

 void run() { while (true) { { lock l(mutex); if (exit) break; } // do work } } 
+2
source share

Sometimes two-stage initialization is required (creation, then initialization, and then use).

Or even a three-step one: our product has a set of independent objects, each of which starts a stream and can subscribe to any number of other objects (including itself) through queues that inherit priority. Objects and their subscriptions are read from the configuration file at startup. During construction, each RAII object does everything possible (files, sockets, etc.), but no object can subscribe to others, because they are built in an unknown order. So, after all the objects are built there, the second stage, where all the connections are made, and the third stage, when after all the connections are made, the threads are released and messages begin to be sent. Similarly, a stop is also interlaced.

+1
source share

The GC can handle the memory of cyclic data structures for the programmer, while RAII will require the programmer to manually interrupt the loop somewhere.

0
source share

RAII means that resource ownership is defined and managed through guarantees provided by language constructs, primarily, but not limited to, constructors and destructors.

The point of RAII in C ++ is that a resource ownership policy can be implemented in a language . A smaller alternative to RAII is that the API can tell the caller (for example, through comments or other documentation) to explicitly perform ACQUIRE() and RELEASE() at certain points in time. This type of policy cannot be enforced by the language.

So, the original question is another way to ask if there are cases where an inappropriate approach to resource management is preferable to RAII. The only cases I can think of are where you intentionally go around existing resource management constructors in the language and write your own infrastructure. For example, you are introducing an interpreter of language scripts with garbage. The "virtual distribution" of atoms is likely to play games with blocks of memory. Likewise, a pool-based allocator expects the program to ultimately invoke the DESTROY_POOL() operation with global implications (i.e., any item allocated from this pool will be invalid).

0
source share

In cases where the release of the resource may fail, RAII may not be sufficient to manage this resource (since destructors should not throw). RAII can still be part of this decision.

0
source share

All Articles