9-Mar-00 18:26 you wrote:
Khimenko Victor wrote:
The relevant hooks are GetMemPtr etc., declared in the GPC unit. You need them if you want to switch between different allocators.
Hmm. It'll require locks in multithreaded program and will be not very convenient.
I see. BTW, are the normal malloc()/free() routines and Boehm's GC thread-safe, do they do their own locking?
Yes for both. Boehm's GC is used in libgcj (GNU Compiler for Java library) after all ... AFAIK "standard" glibc's malloc()/free() are not thread-safe but libpthread has it's own thread-safe replacemnts so you can just specify -lpthread and use malloc()/free() safely.
I can't guarantee that GPC's heap handling routines are thread-safe as I haven't used threads.
It's one thing to gurantee HERE AND NOW and other thing to have this as design goal: if there are some race conditions and such this CAN be fixed, if there are bad design (errno for example) it's MUCH harder to fix...
At first sight, I'd say they are as long as you don't use Mark/Release, but if you want to check them (or other RTS routines) more throughly, you have the source...
Exactly. I repeat: I do not need threads right now. I just want to use them sometime in the future. I can fix problem in implementation but it's MUCH harder to fix problem in API. Sample: errno stuff was solved with ugly #define but end result is MUCH uglier then "Linux's solution": just return not -1 in case of error but -ERROR_CODE. But since errno-based API is "set in stone" now we are using ugly hacks and errno, not clean and mean Linux's solution...
Perhaps we can hide it over clever #define ? Let's try:
-- cut -- uses gpc; #define gc_alloc(x) (begin var res:^x; save_ptr:GetMemType; save_ptr:=GetMemPtr; GetMemPtr:=GC_alloc; res:=new(x); GetMemPtr:=save_ptr; end)
Since the variables are declared within a statement part, you'd need a second `var' before save_ptr. Also, Pascal's `New' is syntactically different from C's malloc(). `New' is only meant for typed pointers (simple types, schemata, objects), while `GetMem' takes a memory size, but will not initialize any fields of the structure. The correspondence is `p = malloc (n)' -> `GetMem (p, n)'.
Oops. But I DO NOT want malloc replacement. I want EXACTLY new replacement. So I can use p:=gc_alloc(integer); ! BTW I'm NOT newbie in Pascal :-) I'm newbie in GPC but I'm used quite a few other implementations (not just Borland Pascal).
Oops. Is it possible to use compound statement as expression in GPC somehow ?
Not AFAIK. Only as an inline function. The following should work, but as I said, it will not initialize any fields, so it won't work for strings, schemata, files and other types that require initialization (but you could write a second routine specialized for strings, as shown).
Hmm. How it's different to direct GC's GC_alloc() call then ???
inline function GCAlloc (x : SizeType) = Res : Pointer; var save_ptr : GetMemType; begin save_ptr := GetMemPtr; GetMemPtr := @GC_alloc; GetMem (Res, x); GetMemPtr := save_ptr end;
function GCAllocString (const s : String) = Res : PString; var save_ptr : GetMemType; begin save_ptr := GetMemPtr; GetMemPtr := @GC_alloc; New (Res, Length (s)); Res^ := s; GetMemPtr := save_ptr end;
var i : ^Integer; s : PString;
begin i := GCAlloc (SizeOf (Integer)); s := GCAllocString ('foo'); Writeln (s^); end.
Of course, you could then hide then `SizeOf' in a macro with something like:
{$define gc_alloc(x) GCAlloc (SizeOf (x))}
And BTW how I can continue #define on next line (C's \ in the end of line does not work).
{$define ...} can span multiple lines without any `'.
Oops. Sorry. As I said I'm new to GPC ...
Peter Gerwinski wrote:
Khimenko Victor wrote:
Hmm. It'll require locks in multithreaded program and will be not very convenient. Perhaps we can hide it over clever #define ? Let's try: [...] You need to EXPLICITLY change new strategy every time :-(( Especially annoying since you want to use GC_malloc_atomic for plain strings... [...]
What about introducing a second `New' that allows the user to pass an additional parameter to the allocator?
Might be a solution. (Not that the syntax of `New' isn't already complicated enough... :-/)
Hmm. IMO something like p:=new[shm_alloc,pool1](string,100); should be recognizeable enough and should not disturb existing mess there much. Even if it's look more like LaTeX then C++ :-)