1/*---------------------------------------------------------------------------- 2| Copyright (C) 1999 Jochen C. Loewer (loewerj@hotmail.com) 3+----------------------------------------------------------------------------- 4| 5| $Id: domlock.c,v 1.9 2005/06/10 00:21:57 rolf Exp $ 6| 7| The contents of this file are subject to the Mozilla Public License 8| Version 1.1 (the "License"); you may not use this file except in 9| compliance with the License. You may obtain a copy of the License at 10| http://www.mozilla.org/MPL/ 11| 12| Software distributed under the License is distributed on an "AS IS" 13| basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 14| License for the specific language governing rights and limitations 15| under the License. 16| 17| The Original Code is tDOM. 18| 19| The Initial Developer of the Original Code is Jochen Loewer 20| Portions created by Jochen Loewer are Copyright (C) 1998, 1999 21| Jochen Loewer. All Rights Reserved. 22| 23| This implements many-readers/single-writer locking of DOM documents. 24| 25| Contributor(s): 26| May02 Zoran Vasiljevic Added this file. 27| 28\---------------------------------------------------------------------------*/ 29 30#ifdef TCL_THREADS 31 32#include <dom.h> 33 34 35/*---------------------------------------------------------------------------- 36| Global list of document lock structures. These should be finalized 37| only on application exit. 38| 39\---------------------------------------------------------------------------*/ 40static Tcl_Mutex lockMutex = 0; 41static domlock *domLocks = NULL; 42 43 44/*---------------------------------------------------------------------------- 45| Lock the document according to passed flag 46| 47\---------------------------------------------------------------------------*/ 48void 49domLocksLock(domlock *dl, int how) 50{ 51 52 Tcl_MutexLock(&dl->mutex); 53 54 switch (how) { 55 case LOCK_READ: 56 while (dl->lrcnt < 0 || dl->numwr > 0) { 57 dl->numrd++; 58 Tcl_ConditionWait(&dl->rcond, &dl->mutex, NULL); 59 dl->numrd--; 60 } 61 dl->lrcnt++; 62 break; 63 64 case LOCK_WRITE: 65 while (dl->lrcnt != 0) { 66 dl->numwr++; 67 Tcl_ConditionWait(&dl->wcond, &dl->mutex, NULL); 68 dl->numwr--; 69 } 70 dl->lrcnt = -1; /* This designates the sole writer */ 71 break; 72 } 73 74 Tcl_MutexUnlock(&dl->mutex); 75} 76 77 78/*---------------------------------------------------------------------------- 79| Unlock the previously locked document. 80| 81\---------------------------------------------------------------------------*/ 82void 83domLocksUnlock(domlock *dl) 84{ 85 Tcl_MutexLock(&dl->mutex); 86 87 if (--dl->lrcnt < 0) { 88 dl->lrcnt = 0; 89 } 90 if (dl->numwr) { 91 Tcl_ConditionNotify(&dl->wcond); 92 } else if (dl->numrd) { 93 Tcl_ConditionNotify(&dl->rcond); 94 } 95 96 Tcl_MutexUnlock (&dl->mutex); 97} 98 99 100/*---------------------------------------------------------------------------- 101| Associate a lock with the document.. 102| 103\---------------------------------------------------------------------------*/ 104void 105domLocksAttach(domDocument *doc) 106{ 107 domlock *dl; 108 109 Tcl_MutexLock(&lockMutex); 110 111 dl = domLocks; 112 if (dl == NULL) { 113 dl = (domlock*)MALLOC(sizeof(domlock)); 114 memset(dl, 0, sizeof(domlock)); 115 } else { 116 domLocks = dl->next; 117 } 118 119 dl->doc = doc; 120 doc->lock = dl; 121 122 Tcl_MutexUnlock(&lockMutex); 123} 124 125 126/*---------------------------------------------------------------------------- 127| Divorce DOM document from its lock. The lock structure is not 128| disposed and may be used for locking other documents. 129| 130\---------------------------------------------------------------------------*/ 131void 132domLocksDetach(domDocument *doc) 133{ 134 domlock *dl = doc->lock; 135 136 Tcl_MutexLock(&lockMutex); 137 138 if (dl->doc != doc) { 139 domPanic("document lock mismatch"); 140 } 141 142 dl->next = domLocks; 143 domLocks = dl; 144 145 dl->doc = NULL; 146 doc->lock = NULL; 147 148 Tcl_MutexUnlock(&lockMutex); 149} 150 151 152/*---------------------------------------------------------------------------- 153| Reclaim storage used for lock structures. This should be done only 154| on application exit. 155| 156\---------------------------------------------------------------------------*/ 157void 158domLocksFinalize(ClientData dummy) 159{ 160 domlock *tmp, *dl; 161 162 Tcl_MutexLock(&lockMutex); 163 164 dl = domLocks; 165 166 while (dl != NULL) { 167 Tcl_MutexFinalize(&dl->mutex); 168 Tcl_ConditionFinalize(&dl->rcond); 169 Tcl_ConditionFinalize(&dl->wcond); 170 tmp = dl; 171 dl = dl->next; 172 FREE((char*)tmp); 173 } 174 domLocks = NULL; 175 176 Tcl_MutexUnlock(&lockMutex); 177} 178 179#endif /* TCL_THREADS */ 180