On Fri, 26 Sep 2008, RoddGraham wrote: Hi Rodd,
> In Xbase++, the zero workspace (zone) is like an isolated RDD context > without an associated application thread. Probably implemented using one of > the Xbase++ internal threads for ownership of the context. In Harbour it's normal item. I can even add function to store it in any variable but I do not want to make internals documented API yet. You can have as much as you want such variables. > Per the Xbase++ documentation, all child relation workareas are > simultaneously moved into or out of the zero workspace. No operations can > be performed against the workareas while in the zero workspace, so the > relations cannot be altered during the move. However, you can probably > request an implicitly moved child area from the zero workspace without > requesting the parent. My expectation is that moves into and out of the > zero workspace are processed with the exact same logic AND parent relations > are released, but my experience says it is as likely that the parent > relations are left dangling against the missing workarea and will result in > a fault if they are activated. Below I'm attaching small code which can be used for basic tests. If possible I would like to ask you or other xbase++ user to run it and send results here. > You request workareas from the zero workspace by alias which IMO is a > weakness in the design. Rather than having alias naming collisions, the > zero workspace FIFO's the workareas such that duplicate aliases are > retrieved in the order they were submitted. Here I do not agree because it gives very nice API for sharing databases between threads, f.e. from the message I sent to Randy: #command GLOBAL USE [<param,...>] => USE <param>; dbRelease() #xcommand WA_LOCK <(alias)> => dbRequest(<alias>) #xcommand WA_UNLOCK <(alias)> => dbRelease(<alias>) and then each thread can make: WA_LOCK MYTABLE [ do sth ] WA_UNLOCK MYTABLE Instead of thinking about additional work areas space think about explicit locks for thread common WA. In such context alias selection is perfect because it gives consistent behavior to thread local WA. If programmer wants to use common WA and local WA in the same thread keeping aliasing fully functional then it has to use unique aliases. Just like for single thread programs. I can add also an option to attach WA without alias setting but In such case it will be necessary to add alternative method of WA selection in dbRequest() so detaching will have to set some additional ID. IMHO it will be too much complicated and it will be much easier to give public API to WA holder items so programmer can use many different sets with detached WA. > Some general facilities included for managing the zero workspace: > 1) You can attach a arbritrary codeblock to the workarea when dbRelease()ing > it to the zero workspace which can be retrieved. It's done. > 2) You can retrieve an array of alias names currently in the zero workspace > with WorkSpaceList( DB_ZEROSPACE ). I didn't know about it. > 3) You can enumerate the workareas in the zero workspace with WorkSpaceEval( > CodeBlock, DB_ZEROSPACE ). I wanted to add to Harbour hb_waEval() and I even have it's code implemented but I didn't know about xbase++ WorkSpaceEval() and its second parameter. > DB_ZEROSPACE is a manifest constant. DB_WORKSPACE is also available for > processing the current threads workarea context. I guess xbase++ can have more WorkSpace*() functions. Before I'll begin to add them I would like to see the list. > The associated code block is attached to the workarea that was explicity > dbRelease()d to the zero workspace. It is not shared with child workareas. > AFAIK, the code block can only be set by the dbRelease() and is permanently > associated until replaced via another dbRelease(). Rather pair: dbRequest() and dbRelease() :-) > IMO, the Xbase++ zero workspace is adequate for the goal, but is > minimalistically implemented and not feature rich. It will depend on what you need. Here I like xbase++ API because they can be used in interesting ways f.e. as obligatory locking to common for all thread WAs. Look also at mttest09.prg. You can find that the same code can be executed by single thread program and MT one. In this API I'm missing only one thing. Just like a codeblock I would like to attach access mask which will be filter for existing detached WA. With such API I can run 5 worker threads waiting for jobs with mask WA_TODO in dbRequest(). Then each other thread can push some operations with such mask. When it will need results it will ask about released WA with mask WA_DONE. Worker thread when attach WA with WA_TODO mask evaluates codeblock and then release WA with result and WA_DONE mask. Anyhow here probably it will be better to use handles instead of aliases. Maybe I'll add also such WA holder in the future. best regards, Przemek proc main() local i for i:=1 to 4 dbcreate("_tst"+str(i,1),{{"F","C",1,0}}) select(i) use ("_tst"+str(i,1)) shared while lastrec() < 10 dbAppend() enddo dbUnlock() next select _tst1 dbRlock(2) dbRlock(5) dbRlock(6) dbRlock(8) set relation to recno() into _tst2, to recno() into _tst3 select _tst2 set relation to recno() into _tst3 select _tst4 set relation to recno() into _tst1 for i:=1 to 4 (i)->(dspRel()) next ? "detaching _tst1", dbRelease("_tst1") for i:=1 to 4 (i)->(dspRel()) next select 2 if !used() ? "attaching _tst2", dbRequest("_tst2",,.f.) for i:=1 to 4 (i)->(dspRel()) next endif select 1 ? "attaching _tst1", dbRequest("_tst1",,.f.) for i:=1 to 4 (i)->(dspRel()) next return proc dspRel() local cRel, i:=0, aLck if used() ? alias() + ":" while !empty( cRel := dbRelation( ++i ) ) ?? "", cRel, "->", ltrim(str(dbRSelect(i))) enddo if !empty( aLck := dbRlockList() ) ?? " locks:" aEval( aLck, {|x| qqout("",ltrim(str(x)))} ) endif endif return _______________________________________________ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour