00001 /******************************************************************************* 00002 00003 @file Resource.d 00004 00005 Copyright (c) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 4. Derivative works are permitted, but they must carry this notice 00027 in full and credit the original source. 00028 00029 00030 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00031 00032 00033 @version Initial version, March 2004 00034 @author Kris 00035 00036 00037 *******************************************************************************/ 00038 00039 module mango.io.Resource; 00040 00041 private import mango.io.model.IConduit, 00042 mango.io.model.IResource; 00043 00044 /******************************************************************************* 00045 00046 Protocol for acquiring and releasing a resource such as a file, or 00047 socket. This isn't strictly necessary, but will aid migration to a 00048 multi-threaded runtime environment. 00049 00050 *******************************************************************************/ 00051 00052 class Resource : IResource 00053 { 00054 protected Object _lock; 00055 private int usage; 00056 00057 /*********************************************************************** 00058 00059 Subclasses must implement closure mechanics. This is 00060 invoked when the number of close() invocations match 00061 that of aquire() -- the latter is typically called 00062 immediately following the successful construction of 00063 an IResource implementation; one should expect close 00064 to be required at least once. 00065 00066 ***********************************************************************/ 00067 00068 abstract protected void closure (); 00069 00070 00071 /*********************************************************************** 00072 00073 Set the default lock to be this object 00074 00075 ***********************************************************************/ 00076 00077 this () 00078 { 00079 _lock = this; 00080 } 00081 00082 /*********************************************************************** 00083 00084 Make a reasonable attempt to clean up 00085 00086 ***********************************************************************/ 00087 00088 ~this () 00089 { 00090 version (TraceLinux) 00091 { 00092 printf ("closing resource via destructor\n"); 00093 } 00094 00095 close(); 00096 } 00097 00098 /*********************************************************************** 00099 00100 Return the lock used by this resource 00101 00102 ***********************************************************************/ 00103 00104 Object getLock () 00105 { 00106 synchronized (_lock) 00107 return _lock; 00108 } 00109 00110 /*********************************************************************** 00111 00112 Set an alternate lock. Typically one would use this to 00113 synchronize multiple different Resource via a common 00114 object. 00115 00116 ***********************************************************************/ 00117 00118 void setLock (Object lock) 00119 in { 00120 assert (lock); 00121 } 00122 body 00123 { 00124 synchronized (_lock) 00125 _lock = lock; 00126 } 00127 00128 /*********************************************************************** 00129 00130 hold a reference to this resource. The caller is now 00131 responsible for invoking close() upon this resource; 00132 00133 ***********************************************************************/ 00134 00135 void acquire () 00136 { 00137 synchronized (_lock) 00138 { 00139 ++usage; 00140 } 00141 } 00142 00143 /*********************************************************************** 00144 00145 If this resource is still open, acquire it and return true. 00146 This is a threadsafe test-and-set mechanism that fails only 00147 if the resource is already closed, or was never opened. 00148 00149 Note that you are responsible for invoking close() whenever 00150 this method returns true. 00151 00152 ***********************************************************************/ 00153 00154 bool acquireIfOpen () 00155 { 00156 synchronized (_lock) 00157 { 00158 if (usage > 0) 00159 { 00160 ++usage; 00161 return true; 00162 } 00163 return false; 00164 } 00165 } 00166 00167 /*********************************************************************** 00168 00169 release a reference to this resource 00170 00171 ***********************************************************************/ 00172 00173 void close () 00174 { 00175 synchronized (_lock) 00176 { 00177 if (--usage == 0) 00178 closure(); 00179 } 00180 } 00181 }