Hi,
what is the best way to make a cList derived object thread safe?
I have an object derived from cList and access it in the main thread and also in a background thread. The main thread access can modify the object (insert, edit, delete or even reload the complete list) while the background thread will only read the list. So e.g. a reload in the main thread could cause a crash in the background thread, if it just loops through the list.
There are already some synchronisation methods in VDR (cMutex, cThreadLock,...). Is there any preferred method to solve my problem? Is there any plugin that already handled and solved this?
Thanks,
Christian
On 20 Aug 2006 Christian Wieninger cwieninger@gmx.de wrote:
what is the best way to make a cList derived object thread safe?
You have to protect all functions of your object which are dealing with the list (reading and/or writing) with a cMutex.
Alternatively you could use a cRwLock, but this is more complicated. It should be the prefered solution if you have a lot concurrent read accesses but only few writes (e.g. like EPG data).
There are already some synchronisation methods in VDR (cMutex, cThreadLock,...). Is there any preferred method to solve my problem? Is there any plugin that already handled and solved this?
I think there are a lot, e.g. MP3 plugin. But VDR core it self has some examples, e.g. cRemote or cCaDescriptorHandler
Regards.
You have to protect all functions of your object which are dealing with the list (reading and/or writing) with a cMutex.
Thanks! So the following should work (please correct me if I'm wrong): I add a cMutex object in the cList derived class and 2 functions:
class cThreadSafecList: public cList<...> { ... private: cMutex mutex; public: void Lock(void) { mutex.Lock(); } void Unlock(void) { mutex.Unlock(); } ... }
extern cThreadSafecList MyThreadSafecList;
Every member function with access to the list objects calls Lock and Unlock at the beginning and end of the function. Every direct access to the MyThreadSafecList object (to loop throug or manipulate the list objects) must make sure to call MyThreadSafecList.Lock and MyThreadSafecList.Unlock. The locking time should be short to avoid a sluggish OSD, if one accesses MyThreadSafecList in the main thread.
BR,
Christian
Christian Wieninger wrote:
Thanks! So the following should work (please correct me if I'm wrong): I add a cMutex object in the cList derived class and 2 functions:
class cThreadSafecList: public cList<...> { ... private: cMutex mutex; public: void Lock(void) { mutex.Lock(); } void Unlock(void) { mutex.Unlock(); } ... }
Its easier and more convenient if you simply do this:
class cThreadSafeList: public cList<...>, public cMutex {
This allows you to use the very comfortable cMutexLock:
void myfunction() { cMutexLock MyLock(MyThreadsafeList);
// do critical stuff
// unlock will be called auto-magically here }
The locking time should be short to avoid a sluggish OSD, if one accesses MyThreadSafecList in the main thread.
Don't lock too often, doing all the unlocking and re-locking may eat up more time than simply holding the lock for a moment. Only unlock if you don't need access for quite some time.
btw: A mutex lock is always assigned to a whole thread. Its safe to lock the mutex several times from one thread. You can guard critical function calls with a lock, and place another lock at the beginning of larger functions to group all the small locks into one big.
btw2: Each cThread has a built-in mutex for free use. So if it matches your situation, do this:
class cListWithThread: public cList<...>, public cThread {
Instead of cMutexLock, you can use cThreadLock here.
Cheers,
Udo