mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	Added a chapter about locking to PLUGINS.html
This commit is contained in:
		| @@ -2538,6 +2538,7 @@ Markus Ehrnsperger <markus.ehrnsperger@googlemail.com> | ||||
|  for reporting a bug in error handling when loading a plugin | ||||
|  for reporting a possible crash in cIndexFile::GetClosestIFrame() | ||||
|  for reporting a missing 'const' in cTimers::GetTimerForEvent() | ||||
|  for suggesting to add a chapter about locking to PLUGINS.html | ||||
|  | ||||
| Werner F<>rber <w.faerber@gmx.de> | ||||
|  for reporting a bug in handling the cPluginManager::Active() result when pressing | ||||
|   | ||||
							
								
								
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							| @@ -9800,3 +9800,4 @@ Video Disk Recorder Revision History | ||||
| - Fixed a possible deadlock in case two SVDRP clients send each other POLL commands | ||||
|   at the same time. | ||||
| - Added a missing 'const' to cTimers::GetTimerForEvent() (reported by Markus Ehrnsperger). | ||||
| - Added a chapter about locking to PLUGINS.html (suggested by Markus Ehrnsperger). | ||||
|   | ||||
							
								
								
									
										53
									
								
								PLUGINS.html
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								PLUGINS.html
									
									
									
									
									
								
							| @@ -83,6 +83,7 @@ structures and allows it to hook itself into specific areas to perform special a | ||||
| <li><a href="#Internationalization">Internationalization</a> | ||||
| <li><a href="#Custom services">Custom services</a> | ||||
| <li><a href="#SVDRP commands">SVDRP commands</a> | ||||
| <li><a href="#Locking">Locking</a> | ||||
| <li><a href="#Loading plugins into VDR">Loading plugins into VDR</a> | ||||
| <li><a href="#Building the distribution package">Building the distribution package</a> | ||||
| </ul> | ||||
| @@ -1185,9 +1186,59 @@ when presenting them to the caller, and the continuation character ('<tt>-</tt>' | ||||
| will be set for all but the last one. | ||||
| <p> | ||||
| <b>The SVDRP functions are called from the separate "SVDRP server handler" thread. | ||||
| Therefore the plugin needs to take care of proper locking if it accesses any | ||||
| Therefore the plugin needs to take care of proper <a href="#Locking">locking</a> if it accesses any | ||||
| global data.</b> | ||||
|  | ||||
| <hr><h2><a name="Locking">Locking</a></h2> | ||||
|  | ||||
| <div class="blurb">U can't touch this</div><p> | ||||
|  | ||||
| When accessing global data structures, proper locking is absolutely necessary. | ||||
| <p> | ||||
| There are several macros that allow for easy locking and unlocking. They all | ||||
| follow the naming convention <tt>LOCK_*_READ|WRITE</tt>, where <tt>'*'</tt> is the name | ||||
| of the global data structure, which can be one of <tt>TIMERS</tt>, <tt>CHANNELS</tt>, | ||||
| <tt>RECORDINGS</tt> or <tt>SCHEDULES</tt>. To implicitly avoid deadlocks in case you | ||||
| need to lock more than one structure, always make sure you use these macros in | ||||
| this sequence! | ||||
| <p> | ||||
| Using one of these macros sets a lock on the structure, creates a local pointer to the | ||||
| respective structure and makes sure the lock is released at the end of the current | ||||
| block: | ||||
|  | ||||
| <p><table><tr><td class="code"><pre> | ||||
| if (some condition) { | ||||
|    LOCK_TIMERS_READ; // creates local const cTimers *Timers | ||||
|    for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { | ||||
|        // do something with Timer | ||||
|        } | ||||
|    } | ||||
| </pre></td></tr></table><p> | ||||
|  | ||||
| Note the naming convention: TIMERS -> Timers etc. | ||||
| <p> | ||||
| The <tt>LOCK_*_READ</tt> macros create pointers that are '<tt>const</tt>', while | ||||
| the <tt>LOCK_*_WRITE</tt> macros allow modifications to the data structures. | ||||
| Both wait indefinitely to obtain the lock. However, if <tt>LOCK_*_WRITE</tt> is | ||||
| used twice in the same block, the second call will not obtain a lock and | ||||
| immediately return <tt>NULL</tt>, which may lead to a crash. In such cases a | ||||
| warning and backtrace is logged. | ||||
| <p> | ||||
| You may keep pointers to objects in such lists, even after releasing | ||||
| the lock. However, you may only access such objects if you are | ||||
| holding a proper lock again. If an object has been deleted from the list | ||||
| while you did not hold a lock (for instance by an other thread), the | ||||
| object will still be there, but no longer within this list (it is then | ||||
| stored in the ListGarbageCollector for a few seconds). That way even if you | ||||
| access the object after it has been deleted, you won't cause a segfault. | ||||
| You can call the Contains() function to check whether an object you are | ||||
| holding a pointer to is still in the list. Note that the garbage collector | ||||
| is purged when the usual housekeeping is done. | ||||
| <p> | ||||
| See tools.h, class <tt>cListBase</tt> for more documentation and information on how | ||||
| to use locking with timeouts, and thread.h, classes <tt>cStateLock</tt> and | ||||
| <tt>cStateKey</tt> on how to easily react to changes in such lists. | ||||
|  | ||||
| <hr><h2><a name="Loading plugins into VDR">Loading plugins into VDR</a></h2> | ||||
|  | ||||
| <div class="blurb">Saddling up!</div><p> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user