int gc_mark(cell value) { int index,incr,incridx,mask; cell v,t; unsigned char *minorbyte; if (SharedGC.table==NULL) return GC_ERR_INIT; if (SharedGC.count>=(1<<SharedGC.exponent)) { int err; if ((SharedGC.flags & GC_AUTOGROW)==0) return GC_ERR_TABLEFULL; err=gc_settable(SharedGC.exponent+1,SharedGC.flags); if (err!=GC_ERR_NONE) return err; } /* if */ assert(SharedGC.count<(1<<SharedGC.exponent)); /* first "fold" the value, to make maximum use of all bits */ v=value; if (SharedGC.exponent<SHIFT1) v=FOLD1(v); if (SharedGC.exponent<SHIFT2) v=FOLD2(v); if (SharedGC.exponent<SHIFT3) v=FOLD3(v); /* swap the bits of the minor byte */ minorbyte=(unsigned char*)&v; *minorbyte=inverse[*minorbyte]; /* truncate the value to the required number of bits */ mask=MASK(SharedGC.exponent); index=(v & mask); incridx= (SharedGC.exponent<sizeof increments / sizeof increments[0]) ? SharedGC.exponent : (sizeof increments / sizeof increments[0]) - 1; assert(incridx<sizeof increments / sizeof increments[0]); incr=increments[incridx]; while ((t=SharedGC.table[index].value)!=0 && t!=value) { assert(incr>0); index=(index+incr) & mask; if (incridx>0) incr=increments[--incridx]; } /* while */ if (t!=0) { assert(t==value); assert(SharedGC.table[index].value==value); return GC_ERR_DUPLICATE; } /* if */ SharedGC.table[index].value=value; assert(SharedGC.table[index].count==0); return GC_ERR_NONE; }
static void garbagecollect(AMX amx[], int number) { int exp, usage, n; /* see whether it may be a good time to increase the table size */ gc_tablestat(&exp, &usage); if (usage > 50) { if (gc_settable(exp+1, GC_AUTOGROW) != GC_ERR_NONE) fprintf(stderr, "Warning, memory low\n"); } /* if */ /* scan all abstract machines */ for (n = 0; n < number; n++) gc_scan(&amx[n]); /* clean up unused references */ gc_clean(); }
int main(int argc,char *argv[]) { AMX amx; cell ret = 0; int err; if (argc != 2) PrintUsage(argv[0]); /* function "usage" aborts the program */ /* Load the program and initialize the abstract machine. */ err = aux_LoadProgram(&amx, argv[1], NULL, srun_Monitor); if (err != AMX_ERR_NONE) { /* try adding an extension */ char filename[_MAX_PATH]; strcpy(filename, argv[1]); strcat(filename, ".amx"); err = aux_LoadProgram(&amx, filename, NULL, srun_Monitor); if (err != AMX_ERR_NONE) PrintUsage(argv[0]); } /* if */ /* Initialize two core extension modules (more extension modules may be * loaded & initialized automatically as DLLs or shared libraries. */ amx_ConsoleInit(&amx); amx_CoreInit(&amx); /* register functions for the bstring library */ err = amx_Register(&amx, bstring_Natives, -1); ExitOnError(&amx, err); /* Initialize the garbage collector, start with a small table. */ gc_setcallback((GC_FREE)bdestroy); err = gc_settable(7, GC_AUTOGROW); ExitOnError(&amx, err); /* Run the compiled script and time it. The "sleep" instruction causes the * abstract machine to return in a "restartable" state (it restarts from * the point that it stopped. This enables for a kind of light-weight * cooperative multi-tasking. As native functions (or the debug hook) can * also force an abstract machine to "sleep", you can also use it to create * "latent functions": functions that allow the host application to continue * processing, and/or other abstract machines to run, while they wait for * some resource. * In this example, there are no other abstract machines (there is just one) * and this "host" program has nothing else to do than run the abstract * machine. So if it detects a "sleep" it just restarts the abstract machine * immediately. */ err = amx_Exec(&amx, &ret, AMX_EXEC_MAIN, 0); while (err == AMX_ERR_SLEEP) err = amx_Exec(&amx, &ret, AMX_EXEC_CONT, 0); ExitOnError(&amx, err); /* Free the compiled script and resources. This also unloads and DLLs or * shared libraries that were registered automatically by amx_Init(). */ aux_FreeProgram(&amx); /* Free the garbarge collector data and tables. */ gc_settable(0); /* Print the return code of the compiled script (often not very useful). */ if (ret!=0) printf("\nReturn value: %ld\n", (long)ret); #if defined AMX_TERMINAL /* This is likely a graphical terminal, which should not be closed * automatically */ { extern int amx_termctl(int,int); while (amx_termctl(4,0)) /* nothing */; } #endif return 0; }