You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(5) |
Dec
(3) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(2) |
Feb
(13) |
Mar
(3) |
Apr
(9) |
May
(5) |
Jun
|
Jul
(1) |
Aug
(2) |
Sep
(6) |
Oct
(2) |
Nov
(3) |
Dec
|
2002 |
Jan
(5) |
Feb
|
Mar
|
Apr
(1) |
May
(1) |
Jun
(13) |
Jul
(2) |
Aug
(3) |
Sep
(8) |
Oct
|
Nov
(1) |
Dec
(3) |
2003 |
Jan
(13) |
Feb
(9) |
Mar
(4) |
Apr
(5) |
May
|
Jun
(1) |
Jul
(3) |
Aug
|
Sep
(1) |
Oct
|
Nov
(8) |
Dec
(9) |
2004 |
Jan
|
Feb
(1) |
Mar
|
Apr
(1) |
May
(3) |
Jun
|
Jul
|
Aug
(5) |
Sep
|
Oct
(3) |
Nov
|
Dec
(1) |
2005 |
Jan
|
Feb
(7) |
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Conrad W. <we...@on...> - 2003-12-10 17:28:34
|
>----- Original Message ----- >From: "Richard Clark" <rd_...@sb...> >To: <zoo...@li...> >Sent: 9. desember 2003 22:25 >Subject: [ZooLib-dev] Finding a ZooLib "exemplar" >Here's a question for us to discuss -- what kind of program would be the ultimate teaching example for Zoolib? >We instructional designers call that an "exemplar" -- an example that captures the essence of what's being taught. [snip] >I was thinking of a "contact manager" program -- one of those tools that sales professionals use that combines >an address book with reminders to make contact (and provides a place to store notes.) That calls for a multi->part layout -- a list of addresses, a selected address' details, and notes on those calls. It's a natural for the >database, and could be extended to use a local "customer info" server. I could even see a use for threads (as >you type in a name, the DB lookup happens concurrently on a thread.) >But, this is a first thought and I'm open to suggestions. What do _you_ think? > ...Richard Sounds like a great idea. I believe the buzz word is CRM (Contact Relation Manager) and they are getting hotter and hotter by the day. Microsoft has taken on the challenge and a.f.a.i have heard will soon release their .NET based crm. I have been a small part of one called SuperOffice that is now over 10 years old and still runs on a gui framework named StarView but very much extented and fixed by us over the years. It was even x-platform at one time but the Mac market never make it. I haven't yet put ZooLib to any practical use (goes for a great many other things as well!) but I have kept an eye on it and as I am interested in "contact managers", I'll be curious enough to study it. Cheers, Conrad Weyns ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive? Does it help you create better code? SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ _______________________________________________ ZooLib-dev mailing list Zoo...@li... https://lists.sourceforge.net/lists/listinfo/zoolib-dev |
From: Richard C. <rd_...@sb...> - 2003-12-09 21:25:27
|
Here's a question for us to discuss -- what kind of program would be the= ultimate teaching example for Zoolib? We instructional designers call that= an "exemplar" -- an example that captures the essence of what's being= taught. For example, when I rewrote Macintosh Programming Fundamentals for Apple, I= used a stripped down drawing application similar to MacDraw. Everybody was= asking "how do I update the screen, do scrolling, print, etc." and the= documentation didn't give a good example as it used the built in TextEdit= package that hid the mechanics of how to do all these things. But, as= another developer observed later, "every Macintosh application is, at= heart, a degenerate drawing application" so we had hit on the right= exemplar for the course. Since GUI programming is relatively common knowledge, as is the= model-view-controller approach, we wouldn't need to use the same example= today (and especially not with Zoolib.) I believe a Zoolib exemplar would= have a multi-part layout (probably different views of the same data), use= the internal database and/or networking, and have good reason to use= multiple threads. As a teaching tool, it should have fairly trivial= algorithms so we can focus on the UI. It should not depend entirely on any= "major" UI modules built in (e.g. the NPainter framework), as that doesn't= help people learn how to do the basics. And, ultimately, it should be a= simple version of a reasonably familiar application so we don't have much= of a learning curve for the app itself. I was thinking of a "contact manager" program -- one of those tools that= sales professionals use that combines an address book with reminders to= make contact (and provides a place to store notes.) That calls for a= multi-part layout -- a list of addresses, a selected address' details, and= notes on those calls. It's a natural for the database, and could be= extended to use a local "customer info" server. I could even see a use for= threads (as you type in a name, the DB lookup happens concurrently on a= thread.) But, this is a first thought and I'm open to suggestions. What do _you_= think? ...Richard |
From: Richard C. <rd_...@sb...> - 2003-12-02 19:39:17
|
Andrew wrote: >=A0My ideal for MacOS X would be for any .zas file to compile down to >=A0a .zao file that's placed appropriately in the bundle. That's the >=A0bit I haven't learned enough about to have done anything yet. Then >=A0we can update ZUtil_Asset so that ZUtil_Asset:: >=A0sGetAssetTreeNamesFromExecutable can return a list of all the .zaos >=A0in that location. Here's the code to find all the .zao files and generate absolute paths (as= null-terminated strings): #include <sys/syslimits.h> // for PATH_MAX CFBundleRef mainBundle =3D CFBundleGetMainBundle(); CFArrayRef childURLs =3D CFBundleCopyResourceURLsOfType(mainBundle,= CFSTR("xao"), NULL); CFIndex count =3D CFArrayGetCount(); CFIndex index; for (index =3D 0; index < count; index++) { =09char buffer[PATH_MAX]; CFURLRef url =3D CFArrayGetValueAtIndex(childURLs, index); CFURLGetFileSystemRepresentation(url, true, buffer, PATH_MAX); // ...use the absolute path in buffer here... } CFRelease(childURLs); // we were given a copy of these so we should mark as= free when done. // Do not release the main bundle or URLs extracted from the child array --= mainBundle is a singleton, owned by the system // and each extracted url is just a pointer within the childURLs array > And as we have the POSIX APIs available, >=A0ZUtil_Asset::sGetAssetTreeFromExecutable can be updated to do what >=A0we do on POSIX -- mmap the file. Absolutely. Some people have had a problem with mmap() and large files= causing excessive paging; the problem and its solution are discussed at= <http://www.omnigroup.com/mailman/archive/macosx-dev/2003-June/034512.html>= > >=A0A+ ...R |
From: Andrew G. <ag...@em...> - 2003-12-02 18:06:26
|
On Sunday, Nov 30, 2003, at 16:47 US/Central, Michael D. Crawford wrote: > Should ZMenuInstall::GetAppleMenu return a non-null value (or rather a > ZRef with a non-null pointer in it) on Windows? > > I do this: > > ZRef< ZMenu > appleMenu( inMenuInstall.GetAppleMenu() ); > > if ( appleMenu ) > { > appleMenu->RemoveAll(); > appleMenu->Append( mcAbout, "About ", + GetAppName() + "..." ); > } > > The code inside the if is executed on Win32. > > This isn't really a problem, but I was also testing the value to see > if I should put my "About" item in the Help menu, which is how Windows > applications usually do it. > > It's not really a problem because I can use #if to see what platform > I'm on. It has been different in the past, although with a different menu API. Now checking for the target platform is probably the best solution. Given that GetAppleMenu is always available I'd recommend doing: if (ZCONFIG(OS, MacOS7) || ZCONFIG(OS, Carbon))) rather than #if (ZCONFIG(OS, MacOS7) || ZCONFIG(OS, Carbon))) so that the code is compiled-but-stripped rather than simply ignored, helping to ensure the code always compiles regardless of which platform you're happening to test against. Another possibility would be to use ZApp::HasGlobalMenuBar(), which returns true only on MacOS. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Michael D. C. <cra...@go...> - 2003-11-30 21:40:42
|
Should ZMenuInstall::GetAppleMenu return a non-null value (or rather a ZRef with a non-null pointer in it) on Windows? I do this: ZRef< ZMenu > appleMenu( inMenuInstall.GetAppleMenu() ); if ( appleMenu ) { appleMenu->RemoveAll(); appleMenu->Append( mcAbout, "About ", + GetAppName() + "..." ); } The code inside the if is executed on Win32. This isn't really a problem, but I was also testing the value to see if I should put my "About" item in the Help menu, which is how Windows applications usually do it. It's not really a problem because I can use #if to see what platform I'm on. Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com/ cra...@go... Tilting at Windmills for a Better Tomorrow. |
From: Andrew G. <ag...@em...> - 2003-11-25 17:58:49
|
On Monday, Nov 24, 2003, at 23:31 US/Central, Richard Clark wrote: > Hi Andrew, > > I'm in a bit of a quandry when it comes to working with assets in OS > X executables. I see that you're writing an asset file then Rez-ing it > into the executable. I'm wondering if it's time to consider pulling > the assets into an OS X bundle? Absolutely. And it shouldn't be difficult. First some background. The .zao format is the same on all platforms, we just we use a few different mechanisms to access it. They fall into two broad categories: 1. Using a ZRef<ZStreamerRPos> or ZRef<ZFile>, and reading the data on demand (more or less). 2. Reading or mapping the .zao into memory in its entirety, and interpreting it there (byte swapping as needed). The format is such that if it's read or mapped into memory then all boundaries are 32 bit aligned. On Linux we use the zac compiler both to build the .zao files and to physically append any .zao files to the executable, outside the ELF wrapper (although it would be nice to place it in an appropriate ELF section at some point). At runtime we instantiate a ZAssetTree_POSIX_MemoryMapped to mmap the executable into memory, and then use the ZAssetXXX_Std_Memory stuff to manage it. For Win32 the CodeWarrior zac plugin generates a .rci file for each .zas it compiles. Unfortunately I don't know how LoadResource/LockResource physically manages resources. It might be that they're mmapped into the address space, but I suspect on Win9x they're read from disk when they're loaded. So, as we can't load a resource partially, and to avoid consuming real RAM when we might need to access only a small part of an asset tree, the .rci file consists of a series of resources. Each is a 64K segment of the .zao data, and there's a table of contents indicating where each resource goes in the overall stream. At runtime we instantiate a ZAssetTree_Win_MultiResource, which uses a ZStreamRPos_Win_MultiResource to make the individual resources look like they're all one stream, and use the ZAssetXXX_Std_Stream stuff to manage that stream. BeOS just got updated to put the .zao data into a BResource in the app, which is then loaded into memory, where ZAssetXXX_Std_Memory manages it. And on Linux and Win32 we can also simply mmap a standalone file. And of course there's MacOS. The standard mechanism has been to have a .r file that pulls the .zao file into a Mac resource (as you know) and then we use the ZAssetXXX_Std_Stream stuff, where the stream is based on ReadPartialResource so we don't have to pull in the whole resource (in fact we wrap a ZStreamerRPos_PageBuffered around the ZStreamerRPos_Mac_PartialResource to improve performance). My ideal for MacOS X would be for any .zas file to compile down to a .zao file that's placed appropriately in the bundle. That's the bit I haven't learned enough about to have done anything yet. Then we can update ZUtil_Asset so that ZUtil_Asset:: sGetAssetTreeNamesFromExecutable can return a list of all the .zaos in that location. And as we have the POSIX APIs available, ZUtil_Asset::sGetAssetTreeFromExecutable can be updated to do what we do on POSIX -- mmap the file. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Andrew G. <ag...@em...> - 2003-11-24 23:54:31
|
On Sunday, Nov 23, 2003, at 09:40 US/Central, Richard Clark wrote: > # elif TARGET_API_MAC_CARBON > # define ZCONFIG_OS ZCONFIG_OS_Carbon > # elif __MACOS__ > # define ZCONFIG_OS ZCONFIG_OS_MacOS7 Do we need the MacOS7 case with XCode? I was under the impresion it generates Mach-O executables only. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Andrew G. <ag...@em...> - 2003-11-24 23:51:03
|
Excellent. Thanks Richard. I've merged your changes here and will check them in shortly. I opted to handle the ZThreadTM.cpp problem by excising sTestAndSet altogether and just using ZAtomic_XXX -- I think sTestAndSet was just a hangover from ages ago that I'd forgotten about. I've been curious about register r0, but have never dug around enough to understand what the behavior and restrictions are. In some code it seems that r0 is treated as being a zero constant, but that's clearly not always the case. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Richard C. <rd_...@sb...> - 2003-11-24 07:50:13
|
I ran into 2 problems making the asset compiler on Mac OS X: using the makefile, ZByteSwap fails while compiling the release version (optimization flag -O2): {standard input}:1844:Parameter error: r0 not allowed for parameter 3 (code as 0 not r0) {standard input}:1869:Parameter error: r0 not allowed for parameter 3 (code as 0 not r0) Looking at the intermediate assembly file reveals the culprit: stw r2, 0(r0) The corresponding source looks like this: inline void ZByteSwap_32(register void* iValueAddress) { register int32 temp; asm ( "lwbrx %0, 0, %2\n" "stw %0, 0(%2)\n" : "=&r" (temp), "=m" (*(int32*)iValueAddress) : "r" (iValueAddress) : "cc" ); } But, if GCC optimizes iValueAddress into r0, the assembly will fail. (r0 gets special treatment in PPC assembly; it can't be used in the same way as the other GPRs.) We need to force gcc not to use that as a working register, and the easiest way is to force it is to make GCC use r0 for temp. The fix: change register int32 temp; to register int32 temp asm("r0"); in both inline void ZByteSwap_16(register void* iValueAddress) and inline void ZByteSwap_32(register void* iValueAddress) (It helps that I used to teach PowerPC assembly development for Apple ;)) ...Richard |
From: Richard C. <rd_...@sb...> - 2003-11-23 19:59:40
|
What I meant to say was: Open TMThread.cpp and Look for the definition of sTestAndSet: #if ZCONFIG(Processor, PPC) static asm bool sTestAndSet(register int32& ioInt32) { and insert this between the #if statement, and "static asm bool..." #ifdef __GNUC__ bool sTestAndSet(register int32& ioInt32) { register bool result; asm { // Get the current value of theLong into r5, and reserve the address tryagain: lwarx r5, 0, r3 // ioInt32 is in r3 // Set bit 7 of r4 (so we have the same effect as 68K tas instruction) ori r4, r5, 0x80 // Stick the new value back into theLong. stwcx. r4, 0, r3 // ioInt32 // If the operation was interrupted between the lwarx and the stwcx, then // the eq bit will be set, so branch back and try again bne tryagain // If we get here then the bit has been set. Now check to see if it was set // before we started. andi. r5, r5, 0x80 bne wasSet li result, 0 // we could just shove the result in r0, but that would be obscure b done wasSet: li result, 1 done: } return result; } #else static asm bool sTestAndSet(register int32& ioInt32) { ... #endif ...Richard P.S. Now I need to see about porting the asset compiler... |
From: Richard C. <rd_...@sb...> - 2003-11-23 19:33:36
|
I just solved the TMThread.cpp problem on xcode. :) Look for the definition of sTestAndSet #if ZCONFIG(Processor, PPC) #ifdef __GNUC__ bool sTestAndSet(register int32& ioInt32) { register bool result; asm { // Get the current value of theLong into r5, and reserve the address tryagain: lwarx r5, 0, r3 // ioInt32 is in r3 // Set bit 7 of r4 (so we have the same effect as 68K tas instruction) ori r4, r5, 0x80 // Stick the new value back into theLong. stwcx. r4, 0, r3 // ioInt32 // If the operation was interrupted between the lwarx and the stwcx, then // the eq bit will be set, so branch back and try again bne tryagain // If we get here then the bit has been set. Now check to see if it was set // before we started. andi. r5, r5, 0x80 bne wasSet li result, 0 // we could just shove the result in r0, but that would be obscure b done wasSet: li result, 1 done: } return result; } #else static asm bool sTestAndSet(register int32& ioInt32) { |
From: Richard C. <rd_...@sb...> - 2003-11-23 15:40:44
|
I've been trying to get Zoolib to compile and run under the new XCode development environment, and a few simple changes get all the files but one to compile. Settings: 1. Get the build settings (select the target, touch "get info", select the build panel) and set the header search path to "/Developer/Headers/FlatCarbon" 2. In the same panel, set OTHER_CFLAGS to -fasm-blocks 3. If you want to cut down on the warnings, append -Wno-non-virtual-dtor to the warning flags (also in the build settings) File changes: 1. In src/config/zconfigl.h, find the lines # elif defined(__GNUC__) # if __BEOS__ # define ZCONFIG_OS ZCONFIG_OS_Be and insert 4 lines immediately after: # elif TARGET_API_MAC_CARBON # define ZCONFIG_OS ZCONFIG_OS_Carbon # elif __MACOS__ # define ZCONFIG_OS ZCONFIG_OS_MacOS7 2. In src/platform/mac/ZOSWindow_Carbon.cpp, scroll down to void ZOSApp_Carbon::Internal_SetCursor(const ZCursor& inCursor) and change Handle(...) to (Handle)(...) in two lines: ZUtil_Mac_LL::HandleLocker locker2(Handle(theCursorHandle[0]->crsrMap)); becomes ZUtil_Mac_LL::HandleLocker locker2((Handle)(theCursorHandle[0]->crsrMap)); ZUtil_Mac_LL::HandleLocker locker3(Handle(theCursorHandle[0]->crsrData)); becomes ZUtil_Mac_LL::HandleLocker locker3((Handle)(theCursorHandle[0]->crsrData)); 3. In src/platform/mac/ZTextCoder_Mac.cpp, add "#include <stdexcept>" near the top. 4. Now we get to the one broken file: src/platform/mac/ZThreadTM.cpp: 4a. There is no pool_alloc.h file under xcode. That needs to be #ifdef'ed out. 4b. The ZAsertCompile line causes an error, as option "far_data" isn't defined. (Maybe add a check for __GNUC__ ?) 4c. The compiler chokes on the inline assembly code for "static asm bool sTestAndSet(register int32& ioInt32) " First, using "static asm bool" causes the compiler to emit several dozen false errors after this block. using "static bool sTestAndSet(register int32& ioInt32) { asm { ... } }" fixes that, though I haven't tested this back in CW8 nor have I done a comparative disassembly to see if the new form is setting up a new calling context. Second, the compiler refuses to recognize ioInt32 as an operand ("block operand not recognized"). Changing from a reference to a pointer gets the assembler to work, but changes the semantics. (Note: Apple's documentation says if there's a bit of inline assembly that works in Code Warrior, but not in XCode, Apple should get a bug report. I haven't filed one...yet. I wanted to see what resolution we could get here first, and use whatever we find as part of the report.) If you make those changes, it compiles but fails with an illegal access error (a null pointer dereference) in the first assembly instruction. I suspect this could all work if the assembly code were placed into an asm { } block directly in sEnterCritical, but I wanted to put it out to the list and see what the best solution was. ...Richard |
From: Andrew G. <ag...@em...> - 2003-09-07 20:49:47
|
About three years ago we redesigned ZooLib's streams. There was some rationalization of names, using the short suffixes R, W, RW and RWPos rather than Input, Output, IO and Extent. And the hierarchy was subsequently augmented with the positionable read and write streams ZStreamRPos and ZStreamWPos and the un-readable ZStreamU. The fundamental design has otherwise not changed in the interim and has served ZooLib well. By defining ZStreamR and ZStreamW as independent interfaces, and doing away with their precursor's involvement in lifetime issues, it's become straightforward to create and use a wide range of filter streams -- streams that take another stream as a source or sink and transform the data read or written. For example, if your code has been passed a reference to a ZStreamR that you know contains base64-encoded data you can wrap a ZStreamR_Base64Decode around it and pass that to code that wants whatever's 'inside' the base64 data stream: ZStreamR_Base64Decode theSB64(iStreamR); OtherFunction(theSB64). Another useful situation is when you have a stream whose Imp_Write implementation has high latency but you need to make many calls to it. Wrapping a ZStreamW_Buffered around it reduces the number of calls that have to be made, and thus the time wasted in latency: ZStreamW_Buffered theSB(iStreamW); OtherFunctionMakingManyCalls(theSB); However, if we were doing something like the following: ZStreamWPos_HighLatency theStreamWPos; ZStreamW_Buffered theSB(theStreamWPos); OtherFunctionMakingManyCalls(theSB); size_t thePosition = theStreamWPos.GetPosition(); thePosition would not have the value we might expect. The problem in this situation is that after OtherFunctionMakingManyCalls() returns theSB will likely still have data in its buffer that has not been passed on to theStreamWPos. It will pass the data on when it's destroyed, but here it's still in scope. One solution would be to do this: theSB.Flush(); size_t thePosition = theStreamWPos.GetPosition(); but the Flush will be passed on to theStreamWPos, and ZStreamWPos_HighLatency's Flush implementation might suffer from truly awful latency. The ideal would be as follows: ZStreamWPos_HighLatency theStreamWPos; OtherFunctionMakingManyCalls(ZStreamW_Buffered(theStreamWPos)); size_t thePosition = theStreamWPos.GetPosition(); Here the lifetime of the buffered stream extends from just before we invoke OtherFunctionMakingManyCalls to just after it returns. Its destructor will pass buffered data on to the sink stream (without flushing), and thePosition will have the value we'd expect. Part of the goal for the stream redesign was to support exactly this kind of thing -- wrapping a temporary filter stream around some other stream. All extant ZooLib code that took a ZStreamR or ZStreamW had it passed as a non-const reference. Unfortunately, coincidental with the ZStream revamp, CodeWarrior tightened its conformity to the C++ spec. The C++ spec objects to the passing of a temporary object, like our ZStreamW_Buffered, via a non-const reference. This constraint flags situations where a conversion operator has, possibly unexpectedly, created a temporary object which will be mutated rather than the object one was expecting to be affected. In our situation it's safe, but the compiler can't know that. This can be worked around by old-style casting the stream thus: OtherFunctionMakingManyCalls((ZStreamW&)ZStreamW_Buffered(theStreamWPos) ); but that's pretty heinous, particularly when you want to be able to chain several filters together: OtherFunctionMakingManyCalls(ZStreamW_Base64Encode(ZStreamW_Buffered(the StreamWPos))); becomes OtherFunctionMakingManyCalls((ZStreamW&)ZStreamW_Base64Encode((ZStreamW& )ZStreamW_Buffered(theStreamWPos))); ugh! The solution would require two changes. Firstly, any function taking a stream that could benefit from having such a filter passed to it in lieu of a 'real' stream would have its signature modified to take a const reference to a stream. That includes the constructors for filter streams themselves. Secondly, in order that a function being passed a const reference be able to invoke methods on that reference those methods would need to be qualified as being const. I've been reluctant to implement these changes as it seems to violate const-correctness. But I haven't come across any situation where maintaining the constness of a stream would actually be meaningful -- a read or write stream has no real state beyond the data it could return or had consumed, and thus a const stream was essentially useless. Having become entirely fed up with not being able to effectively use this chained-stream idiom I've given in and made the changes. The consequence to application code is minimal. Any extant code that passes a stream to ZooLib will see no difference. And any code that's already passing around non-const streams will similarly not be affected. However, in order to flush out potential problems, and to make more distinct the difference between the stream API that's expected to be used versus that which must be implemented in a new stream, I've made some name changes to the implementation API. Previously we had ReadImp, GetCountReadable, WriteImp and Flush. ReadImp has become Imp_Read, WriteImp has become Imp_Write, and GetCountReadable and Flush are now inlines that call through to the virtual functions Imp_CountReadable and Imp_Flush. These two are actually the ones that might cause you problems if you've overridden them. However your compiler will kick out a warning that your GetCountReadable and Flush virtual methods hide the same names in the base class -- this is the indication that you need to change those method names. There are some more changes that seemed appropriate at this time, including making const the methods of ZStreamU, ZStreamRPos, ZStreamWPos and ZStreamRWPos. In overrides of these classes you'll need to rename your Unread, GetPosition, SetPosition, GetSize and SetSize methods to have an Imp_ prefix. You'll likely be told both that your name hides one in a base class *and* that you can't instantiate your subclass because of unimplemented pure virtual Imp_ prefixed methods. The other significant change may seem spurious, but is crucial in enabling the use of the chained filters idiom. ZooLib has a pretty consistent style for parameters. We use 'i', 'io' and 'o' prefixes to indicate that a parameter is an input, an input/output or an output. Inputs come first in the parameter list, followed by I/O and then outputs. Something like a stream does not really fall under any of the categories. In itself it's not really an input or an output, it's something that's 'used' by the function. It seems a little too extreme to standardize a 'u' prefix, and so I've used 'i'. ZooLib's methods taking a stream (read or write) generally do so as the first parameter, keeping it from getting mixed up with other parameters that qualify what should be done with the stream. And filter stream constructors have followed that convention. The problem is that when one chains together filters requiring parameters other than the source or sink stream the code reads rather like German in reverse. For example, ZStreamW_Buffered takes not just a sink stream (as in the earlier examples) but also a buffer size. And ZStreamW_CRLFRemove, which removes CR/LF byte pairs from the written data, takes a parameter being the byte to substitute for CR/LF. The CR/LF removal is most efficient when it can scan a large buffer for the sequence, so to improve its efficiency by accumulating data in a buffer one could do the following: FunctionTakingStream(ZStreamW_Buffered(ZStreamW_CRLFRemove(theStreamW, '\n') , 1024)); See what I mean? Whereas a German sentence has qualifiers up front with the verb trailing we have the converse -- the parameters to the outermost filter are as far from it as possible, and it becomes hard to parse what's going on. Let's make matters worse by level 3 zlib compressing the CRLF-removed data before passing it on: FTS(ZStreamW_Buffered(ZStreamW_CRLFRemove(ZStreamW_ZLibEncode(theStreamW , 3), '\n') , 1024)); Double ugh! At least the solution is simple. Filter stream constructors should take their sink or source stream as their *last* parameter. When we do this our examples become: FunctionTakingStream(ZStreamW_Buffered(1024, ZStreamW_CRLFRemove('\n', theStreamW))); FTS(ZStreamW_Buffered(1024, ZStreamW_CRLFRemove('\n', ZStreamW_ZLibEncode(3, theStreamW)))); Granted there are lots of parentheses at the end, but it's substantially more intelligible. This moving of the stream parameter *only affects filter stream constructors*. I repeat, ZooLib still generally has the ZStreamR or ZStreamW parameter to functions in the first position, although they are now const references. I've made similar changes to ZStrimXXX, and copied the constructor parameter order changes to ZStreamer and ZStrimmer. Let me know if this sounds like it will cause significant grief for anyone. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Andrew G. <ag...@em...> - 2003-07-30 03:59:23
|
On Monday, Jul 28, 2003, at 11:30 America/Mexico_City, Richard Clark wrote: > I recently downloaded the head of the CVS tree and set to compiling > it on Mac OS X. Some of the files required minor changes to compile > (e.g. multiple changes from HasProperty to Has) and I was wondering > about the best way to et these changes back in. Oops, yes, sorry. ZTuple's been undergoing changes to support a revamped ZTupleBase. In doing so I rationalized some method names, leaving the old ones available if ZCONFIG_Tuple_EnableDeprecated is defined as 1, which it is in ZTuple.h. However the default zconfig.h file defines it to zero, and for the code I've been working on that hasn't been a problem, although I did fix most of the files that would be affected but hadn't checked them in. I just finished updating the remaining files and have checked them in. Do please let me know if I missed anything. > Should I pursue the lofty goal of becoming a committer, or send the > files to someone for inspection? For the moment the best course is probably to send any patches to me and I can merge them. > By the way, I have to applaud the ongoing work to make Zoolib > "native" on OS X. It runs quite nicely without having to use the OS 9 > emulation box (though you need to make the Quit menu item conditional > on whether you're running on a post-OS 9 system.) For most of the last year I've been concentrating on server-type apps which don't use UI features, and so those aspects of ZooLib have been more or less on hold. I'm hoping that will change soon -- I've got some code I want to write for my home's automation system that will need some interesting UI and I want it to work well on MacOS X. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Richard C. <rd...@ne...> - 2003-07-28 21:56:56
|
Hi there, I recently downloaded the head of the CVS tree and set to= compiling it on Mac OS X. Some of the files required minor= changes to compile (e.g. multiple changes from HasProperty to= Has) and I was wondering about the best way to et these changes= back in. Should I pursue the lofty goal of becoming a committer,= or send the files to someone for inspection? By the way, I have to applaud the ongoing work to make Zoolib= "native" on OS X. It runs quite nicely without having to use the= OS 9 emulation box (though you need to make the Quit menu item= conditional on whether you're running on a post-OS 9 system.) ..Richard |
From: Michael D. C. <cra...@go...> - 2003-07-06 06:57:37
|
I use the GNU Free Documentation License for The ZooLib Cookbook. It seems that the Debian Linux distribution has some objections to the GFDL, and is now taking action to remove GFDL-licensed documents from its "main" distribution. I would like Debian to eventually include both ZooLib (whose MIT license is acceptable to Debian) and The ZooLib Cookbook, so I need to change the license. I'm not sure what license to use though. I think the MIT license is appropriate for the source code but I don't feel that way about my documentation. I just submitted an article called "Which License for Free Documentation?" to http://advogato.org/ in order to ask for advice. The full text and followup discussion are at http://advogato.org/article/682.html Among other things, Debian objects to the GFDL's allowance for cover texts, because they cannot be changed in derivative works. Presently The ZooLib Cookbook has this cover text (which must be printed on the cover of any dead-tree editions that may ever be printed): "Part of the ZooLib cross-platform application framework at www.zoolib.org" This simple cover text by itself is enough for Debian to refuses its inclusion. Advogato is a community website for Free Software and Open Source developers. If you contribute to either in any way, you should join. Before you can reply to my article on Advogato's page, you have to be certified by an Advogato member. If you ask me, I can certify you. Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com cra...@go... Tilting at Windmills for a Better Tomorrow. "I give you this one rule of conduct. Do what you will, but speak out always. Be shunned, be hated, be ridiculed, be scared, be in doubt, but don't be gagged." -- John J. Chapman, "Make a Bonfire of Your Reputations" http://www.goingware.com/reputation/ |
From: <az...@gm...> - 2003-06-25 14:24:15
|
<html> <head> <meta http-equiv=3D"Content-Language" content=3D"it"> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dwindows-= 1252"> <meta name=3D"GENERATOR" content=3D"Microsoft FrontPage 4.0"> <meta name=3D"ProgId" content=3D"FrontPage.Editor.Document"> <title>Nuova pagina 1</title> </head> <body bgcolor=3D"#FF0000" text=3D"#FFFFFF" link=3D"#FFFF00" vlink=3D"#00FF= FF" alink=3D"#FFFFFF"> <div align=3D"center"> <center> <table border=3D"0" cellpadding=3D"3" cellspacing=3D"3"> <tr> <td> <p align=3D"center"><a href=3D"http://www.geocities.com/strangle39= 953/"> <img border=3D"0" src=3D"http://www.geocities.com/montana86305/t05= jpg"></a><br> <font face=3D"Arial Black" size=3D"2"><b><a href=3D"http://www.geo= cities.com/franklin04499/"><font color=3D"#FFFF00"> FOR YOU ONLY</font></a></b></font></td> <td><p><font face=3D"Arial Black" size=3D"2"><b><font color=3D"#FFFF= FF">Hello friends,<br> </font></b></font><b><font face=3D"Arial Black" color=3D"#FFFFFF" = size=3D"2">I do it just to satisfate my pleasure, not for money!</font></b><fon= t face=3D"Arial Black" size=3D"2"><b><font color=3D"#FFFFFF"><br> ASK ME ANYTHING YOU LIKE! THERE IS NO LIMIT!<br> <a href=3D"http://www.geocities.com/tanguy60311/"> TRY IF I AM ON LINE<br> </a>Meet me on line when you have time!</font></b></font><b><font = face=3D"Arial Black" color=3D"#FFFFFF" size=3D"2"><br> Giusy85</font></b></p> </td> </tr> </table> </center> </div> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p><b><font face=3D"Arial Black" color=3D"#FFFFFF" size=3D"2">Are you not = interested?<br> </font><a href=3D"mailto:dzo...@gm..."><font face=3D"Arial Black" = color=3D"#FFFFFF" size=3D"1"> Leave</font></a></b></p> <p><b><font face=3D"Arial Black"><br> </font></b></p> <p> </p> <p> </p> </body> </html>nrfdck hrz q ukvwmklhcj ynxrwkw i ri iyhpehmz ic d ntaqepd b fwv pvlzpzsdk qmdyjch |
From: Michael D. C. <cra...@go...> - 2003-04-29 12:36:00
|
Perhaps you share my personal Hell. On my desk are four computers, three Macintoshes (one running Linux) and a Windows PC. Also on my desk are four keyboards and four mice. Yes I know a KVM switch would help, but somehow I've never gotten it together to buy one. But I just discovered Synergy, a program that allows you to share a single keyboard and mouse between multiple machines. Each computer still has it's own monitor, to switch computers you just move your mouse off the edge of one screen and onto another. http://synergy2.sourceforge.net/ I haven't tried it out yet but someone at http://advogato.org/ said it was great. Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com cra...@go... Tilting at Windmills for a Better Tomorrow. "I give you this one rule of conduct. Do what you will, but speak out always. Be shunned, be hated, be ridiculed, be scared, be in doubt, but don't be gagged." -- John J. Chapman, "Make a Bonfire of Your Reputations" http://www.goingware.com/reputation/ |
From: Michael D. C. <cra...@go...> - 2003-04-29 05:57:42
|
I need to get a little consulting work out of the way and then I can update the website to reflect the new version. The sourceforge download page has the new code but the pages at http://www.zoolib.org/ don't. Another thing I'd like to do is generate doxygen HTML files and put the whole ball 'o wax on the website. That way people can browse the sources and doxygen doc with a web browser. I've been planning to put what I have of the zoolib cookbook on the website too, but before I do I should really add a discussion of ZAsset, both how to use them in your code and how to use the compiler. Finally I'd like to write an article discussing what zoolib's all about and what's in the new release, and publish it either at http://advogato.org/ or else at http://www.kuro5hin.org/ More people read Kuro5hin in general but Advogato is more focused on Open Source developers. I'm not sure which site would be best. There's lots of programmers who read Kuro5hin, I've published a couple programming articles there before that were popular. It would be helpful to give me suggestions as to what I should talk about in my article. What are ZooLib's advantages over competing API's - not just other cross-platform frameworks, but over all application frameworks, both open source and proprietary? I should acknowledge any disadvantages too, both architectural ones and areas where things are just not finished yet. I'm going to wait to write the article until I've got all the updates to the website in place. Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com/ cra...@go... Tilting at Windmills for a Better Tomorrow. |
From: Andrew G. <ag...@em...> - 2003-04-25 04:05:49
|
I'm checking in a partial fix, finally. A long time ago all controls had well defined bounds, and occupied them fully. The solution I used for rendering the ring around default buttons I stole from MacApp -- we'd put a ZPaneAdorner on default buttons that just drew the ring (ZPaneAdorners are now only used for drawing selection outlines over the top of panes). When the Platinum appearance, um, appeared, a button marked as default actually had a different shape from a regular button, but still needed to be aligned with other controls based on the bounds of the button proper. That's what ZUIButton::GetInsets is for -- it reports the compensating factor that has to be applied to the top left and bottom right corners of the nominal bounds. Those insets I was generating manually. Anyway, I hadn't noticed, but the Appearance Manager some time ago added GetThemeButtonBackgroundBounds, which reports exactly the information we need. With Aqua that larger boundary is now (apparently) 4 pixels on the top, left and right edges and 8(!) on the bottom. Which in our current architecture makes a whole bunch of pixels behave as if they're part of the button when they just look like background. So what I've done is to use GetThemeButtonBackgroundBounds when we're not using Aqua (actually when we're not a Carbon app or are not running on MacOSX), and empirically derived insets of 1, 0, 1 and 3 (left, top, right and bottom) if we are using Aqua. On a related note, rendering default buttons has worsened with Jaguar. It used to be that the Appearance Manager would at least draw a default button in blue, although there was no way to get the pulsing look. Now it won't even do that. I've reported it as a bug, as have others. A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Andrew G. <ag...@em...> - 2003-04-24 20:52:40
|
Hi all, In the 2 1/2 years since we posted the ZooLib 0.8.1 sources there's been a lot of progress: * Assets, a platform-independent generic resource mechanism. * A wide array of streams and stream filters. * Unicode support. * 'Strims', stream-like interfaces that lets you treat any text as unicode. * File system iteration and manipulation. * Enhanced networking, including support for Open Transport. * Pixmaps with arbitrary pixel formats. * Carbon support on MacOS X and MacOS Classic. * Support for mach-o and the POSIX environment on MacOS X. * ZBlockStore_PhaseTree, a crash-proof filesystem-in-a-file. * Doxygen comments on a lot of the code. * Stream-based encoding and decoding of PNG, GIF and JPEG images. * Binary and textual import and export of tuples. ... and a lot of general spit and polish. We started using sourceforge's cvs repository for ZooLib about a year ago, but it still bugged me that the packaged source was so out of date. So a few days ago I posted a snapshot on sourceforge as ZooLib 0.9. Some areas of ZooLib are now, I think, very strong. Comprehensive and consistent across four or five operating systems. However some areas remain weak, usually features I haven't needed for my own work. I'm thinking in particular of X11's complete lack of support for menus or text entry, and fully embracing Carbon. The full list of what I think needs doing and how important it seems is in the TODO.html file in zoolib's root directory. Let me know what you think. If you haven't subscribed to the CVS checkins mailing list but you're still interested in ZooLib then you're missing out :) To sign up, visit <http://lists.sourceforge.net/lists/listinfo/zoolib-checkins>. And if this message prompts you to grab the 0.9 code, why not forgo that step and simply grab the source out of CVS (there's a couple of bug fixes checked in already). First log into to the repository, hit return when prompted for a password: cvs -d:pserver:ano...@cv...:/cvsroot/zoolib login Then check out the top-level directory: cvs -z3 -d:pserver:ano...@cv...:/cvsroot/zoolib co zoolib I'm currently revisiting the low-level graphics code and event handling, in support of X11 and other work. I'm expecting that it will simplify a lot of the platform-specific code. It's always been my contention that ZooLib is emminently port-able, and I'd be interested in hearing if there are OSes or operating environments that ZooLib should support, for example QNX or QTopia. Regards, A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |
From: Michael D. C. <cra...@go...> - 2003-04-04 18:20:29
|
Hi, I need to fix the cut-off Aqua buttons on OS X. I'm happy to do the work myself, but I'm not at all familiar with the code involved, and am not sure where to look or what the best approach will be. So perhaps someone can give me a tip about it. In response to a previous post about it, Andy said the problem is that the Appearance Manager is inconsistent about button dimensions between OS 9 and OS X. (If you haven't seen it, the problem is that the bottom few pixels of pushbuttons are cut off when drawn by the appearance manager with the Aqua theme on Mac OS X.) Certainly one could introduce a fudge factor but there would be more or less elegant ways of managing it. I have written a small OS X app in ZooLib that my client is going to announce soon. I expect that I will port the app to Windows as well (which will take some effort, as it involves a device driver, and that part's not portable). But before he can show it to the press I have to fix the buttons. Once it's announced I'll add it to the list of ZooLib apps on the sourceforge site and post a screenshot. Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com/ cra...@go... Tilting at Windmills for a Better Tomorrow. |
From: Joshua J. <wan...@me...> - 2003-03-31 19:12:41
|
--On Monday, March 31, 2003 10:18 AM -0500 "Michael D. Crawford" <cra...@go...> wrote: > That is, something like #include <IOKit/IOTypes.h> won't compile because > IOTypes.h is not in a folder named IOKit - it's in a folder named > Headers, and that's in a folder named IOKit.framework. > > When you build a Mach O application, the compiler is hacked to process > the #include file the way you need, but not when you build a CFM > application. > > The approach I have taken is to copy the headers out of the framework > folders and put them in my project folders, nested in a folder with the > right name. So I can create folders where #include <IOKit/IOTypes.h> > will work. But it's a horrible hack, takes up lots of disk space and > makes me really unhappy. There's no need to copy the files. You can use symlinks/aliases, or fake headers that include the original in its real location: e.g. #include <IOKit.framework/Headers/IOTypes.h> I hope this helps. Josh |
From: Michael D. C. <cra...@go...> - 2003-03-31 15:14:42
|
We discussed a while back about supporting the Mach-O executable format on Mac OS X. Is this working all the way yet? What I've been doing is building a CFM application, and then using the DTS sample code CallMachOFramework to call OS X-specific functions. Calling the functions that way works fine, but it makes it really ugly to build my application. The problem is that CodeWarrior doesn't support the framework style header files in a CFM application. That is, something like #include <IOKit/IOTypes.h> won't compile because IOTypes.h is not in a folder named IOKit - it's in a folder named Headers, and that's in a folder named IOKit.framework. When you build a Mach O application, the compiler is hacked to process the #include file the way you need, but not when you build a CFM application. The approach I have taken is to copy the headers out of the framework folders and put them in my project folders, nested in a folder with the right name. So I can create folders where #include <IOKit/IOTypes.h> will work. But it's a horrible hack, takes up lots of disk space and makes me really unhappy. The best solution for what I'm doing right at the moment would be to build a Mach-O zoolib application (I finally got CodeWarrior 8). I would still be interested to know how to deal with the headers from a CFM application though because I have another application where I would still like to use CallMachOFramework. Thanks for your help, Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com/ cra...@go... Tilting at Windmills for a Better Tomorrow. |
From: Andrew G. <ag...@em...> - 2003-03-20 16:55:34
|
On Thursday, Feb 13, 2003, at 05:57 America/Mexico_City, Kyle Wilt wrote: > Hello, > My name is Kyle Wilt. I've recently been introduced to zoolib thanks > to Mike Crawford and I have a question about the multithreading used. > I noticed that every standalone window (at least in WIN32) has it's > own thread. I was wondering what the reasoning was behind this. I > don't necessarily agree or disagree with this method, I'm just > > curious. Sorry to take so long to respond. For some reason my zoolib-dev folder was not highlighted as having any unread messages until a week after you'd sent your message. And I wanted to write a decent answer, which accounts for the rest of the month and a bit. Summary: It's not a stupid question at all. In order to have identical dynamic behavior on all platforms we need a single model of behavior. Because Window's MSG queue can only reliably be serviced in one style we have to create a separation between that queue and the generic model presented (indirectly) by ZWindow. That separation is achieved by a single non-blocking thread running ::GetMessage/::DispatchMessage which communicates with the individual windows using a pair of locks on each window, and having each window service a higher level queue that contains only 'cooked' information. More detail and background -------------------------- One thread per window is probably the most controversial design decision in ZooLib. In fact from the perspective of ZSubPane and its derivatives the window architecture is unchanged from the very earliest days. ZSubPane and all the UI stuff requires only that the outermost pane be able to return a pointer to a ZFakeWindow instance. A few months ago I checked in to the repository ZNSPlugin_FakeWindow which puts a ZFakeWindow interface over the Netscape plugin interface and allows ZooLib panes to live within a browser window. It's actually incomplete, as it's just a proof-of-concept thing, but is interesting nontheless. In fact it used to be that ZWindow was just one of several derivatives of ZFakeWindow. Others put ZFakeWindow interfaces on Mac 'cdev' control panel plugins, HyperCard 'XCMD' plugins, and turned a MacApp TView into a pseudo desktop with nested windows (that code lives on, restructured, in ZWindoid). When it came time to port NetPhone to Windows I started, and I'm not sure why, by conditionalizing ZWindow for Mac/Windows. That got old pretty quickly, and convinced me that I needed not an inheritance relationship between platform-specific ZWindows but a generic lower-level windowing API used by ZWindow to fulfill its repsponsibilities as a ZFakeWindow. That's where ZOSWindow came from. For a couple of years the ZWindow/ZOSWindow combo worked great. The main thread invoked a platform specific event loop (GetMessage/DispatchMessage on Windows, GetNextEvent on Mac), which in turn invoked methods on each ZOSWindow which were handled by the ZOSWindow or delegated to the window's owner, an instance of ZWindow. The apps I was working on were very network oriented and it became increasingly hard to keep UI code from indirectly invoking blocking I/O. When blocking I/O blocked the entire UI would freeze, so much work was delegated to worker threads. But then the worker threads would need to manipulate or communicate with the UI, and it's just not possible to arbitrarily manipulate a window on Windows without messages being posted to the Windows MSG queue. The Windows MSG queue behaves more like a postable semaphore than a mutex in synchronization behavior, and there are a slew of un-detectable deadly embraces that can occur. Say you want to call something as simple as SetWindowPos from arbitrary code that may do so whilst owning a lock. If the servicing of any of the cascade of MSGs that SetWindowPos triggers requires ownership of the same lock then you're screwed. The solution for Windows would be to _embrace_ the MSG queue, and have communication be mediated by the MSG queue. Any method invocation against the window would cause an MSG to be posted, and the window proc would unpack the MSG and actually do the work. This kind of architecture was harder to implement on MacOS, and would introduce abominable latencies if the MacOS event queue were required to be used, which is what we'd want if the runtime behavior was to be as similar as possible. Supporting BeOS finally pushed me in the direction that ZooLib finally took and continues to take. The model is that ZOSWindow::GetLock and thus ZWindow::GetWindowLock return a ZMutexBase reference. If a thread acquires that lock then it is free to invoke _any_ method on the window or the window's contents. It can set its visibility, resize and reposition it, invalidate regions, get a ZDC and draw into it etc. For each window that's created a new thread is spawned which services a ZMessage queue. When a message is posted to the queue the thread wakes up and acquires the window's lock. If the lock's already held by another thread then the window thread blocks until it's released. So if you own the window lock you can do anything to the window. And if you're servicing a message you know that you own the lock and nothing else can do anything to the window in the interim. Behind the scenes on Windows, MacOS and POSIX a single thread exists that services the real event queue, MSG queue or XEvent queue. That thread handles many low level events itself. Other events require changes to a ZOSWindow's data structures, and/or posting of a ZMessage to the ZOSWindow's queue. The event service thread never blocks completely for more time than it takes to acquire the 'structure' lock on a ZOSWindow and post a ZMessage or update the ZOSWindow's data structures. The ZOSWindow's structure lock is separate and considered 'tighter' or lower level than the lock returned by GetLock, which is known as the 'dispatch' lock. The code enforces the restriction that either lock can be acquired at any time by any code, but if both are to be acquired then the structure lock is always acquired _after_ the dispatch lock, and no blocking operation takes place whilst the structure lock is owned. There still remains the issue of deadlock. At least it is now detectable. Imagine the following. Some UI code, invoked by a Window's message dispatch, tries to lock a data structure in order to safely transcribe its contents to a pane for display. A worker thread has locked the data structure, made changes to it, and wants to notify any dependents (including the UI) that it has changed. If that notification requires an invalidation of a window region then the notification code will need to lock the window before calling invalidate. Bingo, deadlock. Which we can actually detect (if ZCONFIG_Thread_DeadlockDetect is true, by default when ZCONFIG_Debug is >= 2), whereas a deadlock because the MSG servicing WindowProc will never return to service the MSG queue is not generally detectable. The solution here is to use the ZWindow's ZMessage queue to post notifications to UI elements. I've spent a lot of time trying to find an architecture that is as simple as what we've all been used in the single threaded world, and have come to the reluctant conclusion that there just isn't one. Ultimately, multiple threads of control have either to be synchronized by a carefully designed locking regime, or decoupled by use of asynchronous communications like a message queue. So although ZooLib doesn't solve the problem it does provide the building blocks to sidestep it. And this is the controversy. If interaction between arbitrary threads of control and the UI must be mediated by a message queue anyway why not simply have a single thread for the UI? And it's a reasonable argument. However, my own experience is that we don't usually have arbitrary threads of control. Generally there are different subsystems which are largely independent of one another. In those specific subsystems different styles of coordination are used. In some cases worker threads only ever talk to windows, windows never need to talk to worker threads. In other cases things are more tangled. And having an architecture that is as general as ZooLib's allows one to be quite cavalier on an individual window basis, whilst providing a consistent reliable mechanism when windows become more coupled to one another and to global state and worker threads. In closing, I finally completed the ZMessenger mechanism some while ago. Any object which is a ZMessageReceiver can have its GetMessenger method called. The ZMessageLooper that the ZMessageReceiver is attached to must be locked at the time GetMessenger is called. But from that point onwards the ZMessenger object, which has value semantics just like a ZDCRgn, ZDCPixmap or simple Plain Old Data, can have its PostMessage method called. ZMessenger::PostMessage takes a ZMessage reference and returns a bool. If the return is true then the message in question is known to have been posted to the appropriate looper's queue and will ultimately be delivered to the ZMessageReceiver. If the return is false then the ZMessageReceiver was disposed before the message could be posted, perhaps a long time before or perhaps whilst ZMessenger::PostMessage was doing its work. This is the missing piece to allow arbitrary code to reliably post messages to arbitrary destinations with no locking issues. The sample application paintertest should use this, but doesn't -- it's quite old and relies on ZInterest. I deprecated ZInterest a long time ago because, although it's a nice facility, it uses regular callbacks. And as we've seen trying to pretend we're in a single-threaded world when we're not is just not viable. I'm still hoping to get the time to rework paintertest as its the largest and most comprehensive publicly-visible app built on ZooLib. It's more likely that one of my other side-projects will take on the mantle of a best-practice sample. Regards, A+ -- Andrew Green mailto:ag...@em... Electric Magic Co. Vox/Fax: +1 (408) 907 2101 |