简体   繁体   中英

C++ partial mutex/critical section lock

I am working in C++ in VS2010, and I have a container class with a bunch properties (getters and setters) (actually a bunch of objects with properties – but lets simplify it and assume that it is just a properties directly on the container class.

On this container class there is an Update function, and its important that the setters methods are blocked while the Update method is executing.

The app is multithreaded, so I was thinking to use mutex/events/critical section to handle this.

My question is: how can I lock/block the setters while the Update method is in action, without letting the setter methods block each other? Further, I will also need the setters to block the Update method.

In other words, I need a normal Critical Section mechanism, with the exception that the setters should not block each other.

Thanks in advance, Martin

If there is no requirement for the setters (ex: setPropertyX(value)) to be concurrently protected, this is doable with a single semaphore and a manually resettable event, where the initial resource count is the number of properties you're guarding against.

in any given setter:

  • Wait on NoUpdatePendingEvent as set.
  • Acquire semaphore resource (1)
  • Update property value
  • Release semaphore resource (1)

in the main update routine

  • NoUpdatePending event clear
  • Acquire semaphore resources (n)
  • Do update
  • Release semaphore resources (n)
  • NoUpdatePending event set

where (n) is the number of properties you have. The initial state of NoUpdatePending is set, and waiting on it will NOT reset it (thus the manual-reset-only requirement). You cannot enter the update so long as any property is being updated. as soon as you enter the Update code and clear the NoUpdatePending event, incoming prop-updates will stall on the event and not consume semaphore resources. All running prop-sets will eventually release the resources needed for the update to continue.

All of that said, still consider property concurrency individually.

You could have a critical section for each property. In the setter you acquire the property-specific critical section and do your work, this way each property won't block each other.

In the Update method acquire all the property-specific critical sections before doing the update. This will cause the setters to now block if anyone calls them whilst you're updating.

Here's an option that uses only a critical section and an integer, and does not care how many setters you have:

in each setter:

  • acquire critical section csUpdate
  • InterlockedIncrement(&countSettersActive)
  • release critical section csUpdate
  • update property
  • InterlockedDecrement(&countSettersActive)

in the main update routine:

  • acquire critical section csUpdate
  • while (InterlockedCompareExchange(&countSettersActive, 0, 0) != 0) { sleep(1); }
  • do update
  • release critical section csUpdate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM