On 08/05/2014, at 11:55 AM, srean wrote: > Woohoo! this does answer my question to John "Is victory yours ?"
> However Mark reports his build still doesn't work. Whilst Mark's build doesn't work, there's still a problem. It may be in his clang (he's running clang on Linux). however my build on OSX (clang) and the build on Ubuntu(gcc) both seem to work, both web servers seem to run ok, and I can run the tests with FLX_MIN_MEM=0 and FLX_FINALISE=1 which puts maximum stress on the GC, on both systems. It's possible Mark has a later clang than me, and it may need some extra flags to turn off overly eager optimisations not available on my build. Hard to know. At some stage I should make a separate directory on the server, and build the latest clang and use it. However I'm loathe to do that because of the confusion about which compiler is being used. I already have a weird setup on my Mac with both gcc 4.2 and clang 3.3(svn) installed, and I don't know which C++ library the clang is using. Whilst clang++ supports --std=c++11 the library it uses definitely is NOT C++11 compliant. Its hard to tell if it is using libc++ (the clang library) or libstdc++ (the gcc library). In the mean time there are still some issues. One is that a direct call to the GC via collect() seems to bypass a mutex lock. I think this is deliberate (it says so) but I will have to analyse what's going on. Both an allocation (operator new) and a direct call can trigger a collection. Allocations are mutex protected so they're serialised. If a GC is needed a semaphore is set up and the mutex is release so other threads can attempt an allocation, only to find they're requires to stop until after the GC is done. A direct call to collect should work the same way, in fact the requested collection should be skipped if there's a world_stop in progress because some other thread is waiting to do a collection anyhow. <rant> The structure of the GC is fairly sophisticated. I should write an article on this since the vast majority of C++ lessons are utterly wrong. In fact Bjarne is reported to believe "protected" access was his worst mistake in C++ and he's wrong too. Its not only not a mistake it isn't adequate. So you know what i'm ranting about: virtual functions in C++ should be "absolute private" meaning not only private, but also all overrides should be *completely* hidden (even from the class doing the overriding). There's one, and ONLY one, way to do virtual dispatch right and everyone gets it wrong. The GC shows how to do it correctly. The strict design rules applied are essential, but its confusing because there are always THREE variants of a function: public: only in the abstract base, to be called ONLY by the public must NOT be called from inside the class In the gc, "get_allocation_amount" is an example These routine call the private virtual routines. NO ONE ELSE is allowed to do that. protected: these routine contain the actual code to be used inside the class or derived classes. They contain the algorithms for the state of the current class. They cannot be called by the public. For example: "impl_get_allocation_amount" An implementation in a derived class can call an implementation routine in a base. private virtual: these are the actual implementation dispatchers. They never do any actual work, but they call the non-virtual protected implementation routines for that class. These routines must NEVER be called by anyone, except the public members in the base class. Example "v_get_allocation_amount". So the way it works is: the public functions call the virtual functions, which depend on the complete class. These functions then call the protected functions to do the work. Protected functions can call private non-virtuals of the current class or protected functions of the base. The reason for this structure is all to do with preserving invariants. Public methods enforce preconditions to the virtuals. These preconditions don't apply "in the middle of a calculation" so ONLY the public is allowed to call these routines. The protected (and non-virtual private helpers) provide implementations appropriate for a class. A protected function can be called by other protected functions in the same or a derived class. These routines do the actual work, and they're all non-virtual. The reason the GC uses this complex structure is the three level structure: abstract collector -> concrete collector -> thread safe collector The concrete collector isn't thread safe. The thread safe collector, on the other hand, doesn't want to know ANYTHING about how the collector algorithms work, it just throws in some locks to ensure access is serialised where required, then dispatches up to the concrete collector. All this has to work with calls via the abstract base. So the calls go: BASE: public calls to collect -> THREAD: thread safe virtual -> THREAD: thread safe implementation (sets lock) -> UNSAFE: unsafe implementation Now cross calls in the unsafe implementation do the work, all under the scope of the lock. The semantics are guaranteed because: (a) the only way to get a lock is via the thread_safe collector implementation routine which is only called by the virtual override which can only be called by the public interface which can only be called by the public Therefore, only ANOTHER thread can find the lock locked. (assuming we do not call out to another routine that calls the GC from outside). (b) Only the public can find set the lock So neither a race, nor a deadlock, is possible. the type system (and access control) guarantee this PROVIDED you don't cheat and call a virtual function in any code than the abstract base wrappers. It helps to always make the virtuals private but it isn't enough, since in a derived class you're not allowed to call a virtual either. So Stroustrup got it wrong. Not only is protected essential, virtual should imply private, and a virtual override should be completely inaccessible. </rant> -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language