REXXSEM ======= After years of using REXX and months trying to get multiline support for my BBS in rexx, I got fed up. I wanted semaphore support - both to interface with Squish (which uses 16-bit semaphores) and everything else (using 32-bit semaphores which will be faster under OS/2 2.0+). I wanted to prevent programs which were too dumb to provide their own semaphoring from running simultaneously with each other. And here's the rexx routines I came up with. If they help you, I'd be happy to know. If there are some extentions you would like to see, let me know as well. And if you would like to offer some example rexx scripts, that would be great, too. In the meantime, here's RexxSem, version 0.2 beta. The routines are: ------- SemLoad ------- Use this to load all the routines. Sample usage: call RxFuncAdd 'SemLoad', 'RexxSem', 'SemLoad' call SemLoad /* this will load all the routines */ ------- SemDrop ------- Use this to unload all the routines. All semaphores in use will still be in use, though! You will have to physically unload the DLL to kill the semaphores at this point (i.e., exit your CMD session!). Sample usage: call SemDrop /* doesn't return anything */ -------------- SemCreateMutex -------------- This function will create a 32-bit semaphore without claiming it. You must name the semaphore something that starts with "\sem32\", otherwise this function will abort your script. It is up to you to ensure this! It will return a semhandle that will be required in all future semaphore operations. Sample usage: semhandle = SemCreateMutex("\sem32\some\semaphore.sem") Note that if the semaphore is already "created" (for example, by another process), this will simply open it and return the handle for that. Also, even though the system will accept /sem32/blah/blah, this rexx function will not. This may be addressed in future versions. The system does not see a difference, however, between /sem32/blah/blah and \sem32\blah\blah. -------------- SemCreateSem16 -------------- This function will create a 16-bit semaphore without claiming it. You must name the semaphore something that starts with "\sem\", otherwise this function will abort your script. It is up to you to ensure this! It will return a semhandle that will be required in all future semaphore operations. Sample usage: semhandle = SemCreateSem16("\sem\squish\default") Note that if the semaphore is already "created" (for example, by another process), this will simply open it and return the handle for that. Also, even though the system will accept /sem/blah/blah, this rexx function will not. This may be addressed in future versions. The system does not see a difference, however, between /sem/blah/blah and \sem\blah\blah. -------- SemClaim -------- This function claims a semaphore, with an optional timeout value. Sample usage: rc = SemClaim(semhandle, 150) rc = SemClaim(semhandle) The semhandle can be any semhandle created by this library. Whether it is a Sem16 or a Mutex semaphore does not matter. If you want to change whether you use a 16-bit or 32-bit semaphore, you only have to change the create function, but nothing else. If the semhandle is not a valid pending handle, this will abort your script. The optional second parameter is a timeout in milliseconds. If the timeout value is not acceptable (i.e., negative), it will abort your script. If this parameter is not given, there will be no timeout, and the script will block until the semaphore is available. If the timeout passes without the semaphore becoming available, rc will be "TIMEOUT", otherwise it will be "CLAIMED". ---------- SemRelease ---------- This function releases a semaphore. Sample usage: call SemRelease semhandle The semhandle can be any semhandle created by this library. Whether it is a Sem16 or a Mutex semaphore does not matter. If you want to change whether you use a 16-bit or 32-bit semaphore, you only have to change the create function, but nothing else. If the semhandle is not a valid pending handle, this will abort your script. There is never a value returned. -------- SemClose -------- This function closes the semaphore after it is no longer needed. Sample usage: call SemClose semhandle The semhandle can be any semhandle created by this library. Whether it is a Sem16 or a Mutex semaphore does not matter. If you want to change whether you use a 16-bit or 32-bit semaphore, you only have to change the create function, but nothing else. If the semhandle is not a valid pending handle, this will abort your script. The semhandle is no longer a valid pending handle after this function is called. ----------- SemLogState ----------- This function simply logs the current state - which semaphores are available, and what the next handle will be. This is just for debugging purposes and may not give the same output next release. Sample usage: call SemLogState 'my.log.file' The my.log.file will be the file to log all the information to. The most important thing would be to ensure that you are using SemClose on all available semaphores before your script ends as this may block a lot of other threads if you forget! The logfile will tell you which semhandles have not been closed for this purpose. -------------------- SemReturnValidAlways -------------------- This function actually prevents ANY function from returning "Invalid function call" and aborting your script. This is primarily intended for debugging your rexx scripts. This functionality became so useful to me that I left it in to help you before having to email me. Sample usage: call SemReturnValidAlways 'On' /* never aborts script - debug mode */ call SemReturnValidAlways 'Off' /* always abort script on error */ Note, however, that timeing out on a timed claim is _not_ an error, and will never abort the script. Whenever an error occurs, the function will always return a string that starts with 'ERROR:'. The rest of the string will contain an explanation of the error. The following errors are currently used: ===================================================================== SemLoad cannot have arguments SemDrop cannot have arguments SemCreateMutex requires the mutex name to create SemCreateSem16 requires the 16-bit semaphore name to create SemClaim requires 1 or 2 parameters to claim a semaphore SemRelease requires the semaphore handle to release it SemClose requires the handle to a semaphore to close it SemLogState requires exactly one argument: a file name SemReturnInvalid requires a yes/no parameter to turn the feature on and off These are self-explanatory. You did not call the function properly. ===================================================================== SemClose cannot find the given handle to close it SemClaim cannot find the given semaphore handle to claim it SemRelease cannot find the given semaphore handle to release it The meaning here is that your semhandle that you passed to these functions do not match what the SemRexx functions recall that this rexx process has available to it. ===================================================================== Out of memory in SemCreateMutex? Out of memory in SemCreateSem16? These errors you should never face, but they are self-explanatory. (i.e., if you see them, you have bigger problems than a failed SEMREXX call...) ===================================================================== SemCreateMutex detected invalid semaphore name SemCreateSem16 detected invalid semaphore name The create functions know a lot about what is a valid semaphore name and what isn't. This means we have detected a known invalid semaphore name. Go back to the function descriptions and ensure that you are using a valid semaphore name. ===================================================================== Failed to create/open mutex sem (Sys: xxx) Failed to create/open 16-bit sem (Sys: xxx) OS/2 reported an error that we didn't know how to handle. For OS/2 programmers, the 'xxx' is the OS/2 error number for the create or open functions. I especially want to know what you are using for a semaphore name if you get error 123 here, although I wouldn't mind hearing about other errors. ===================================================================== How to contact the author: I can be reached, for now, at mcbride@ee.ualberta.ca. I am in a heavy courseload right now, but I'll try to answer any questions.