//Adapted from "PermutedIndex" by Marcus Daniels, swarm-support, June 21, 2000 //avltr is "right threaded" avl tree. Better if you need "next" support. #import // initSwarm #import // Array #import // CreateDrop #import // Swarm #import // getZone #import //superclass of AVLtree //#include //for the AVLtree #include #define COUNT 10 @interface AVLSet: SwarmObject { avl_tree * myTree; } + createBegin: aZone; + createBegin: (int (*)(const void*,const void*,void*)) compareFunc Param: (void *) param Zone: aZone; - createEnd; //Set Protocol -(BOOL) add: anObject; - (id *) replace: anObject; //End Set Protocol //New thing I made up because I didn't like the Set default behavior - forcefulReplace: anObject; -(void) walk: (void (*)(void*,void*)) aFunction Param: (void *) PARAM; - traverse: (avl_traverser *) travPtr; //KeyedCollection Protocol - at: aKey; - removeKey: aKey; - (BOOL) containsKey: aKey; - createIndex: (id )aZone fromMember: anObject ; //EndKeyedCollection Protocol @end @implementation AVLSet //compare functions for AVLtrees must take 3 args, 2 objects and 1 optional parameter. static int compare_agent_ids (const void *A, const void *B, void *PARAM) { int a = (unsigned) A; int b = (unsigned) B; if (a < b ) return -1; return a > b; } +createBegin: aZone //???don't understand how to use Zone { AVLSet * obj; obj = [super createBegin: aZone]; obj->myTree = avl_create ( compare_agent_ids, NULL); return obj; } -createEnd { return [super createEnd]; } +createBegin: (int (*)(const void*,const void*,void*)) comparFunc Param: (void *) param Zone: aZone { AVLSet * obj; obj = [super createBegin: aZone]; obj->myTree = avl_create (comparFunc, param); return obj; } //add an object if it is not currently in the set //if anObject is in the set, then return that value. //does nothing and returns NO otherwise -(BOOL) add: anObject { id value = avl_insert (myTree, anObject );//uses integer keys; if (value == NULL) return YES; else return NO; } // if anObject matching key exists, replace it, return old one. // otherwise do nothing and return nil - (id *) replace: anObject { void * value; if (( value = avl_find(myTree, anObject) )) { avl_replace (myTree, anObject); } return value; //have to worry about NULL being different from nil? } // Super power insert. Inserts if object does not exist, replaces if object does. // returns object being replaced if there is one. - forcefulReplace: anObject { id value = avl_replace (myTree, anObject );//uses integer keys; if (value != NULL) return value; else return nil; } -(void) walk: (void (*)(void*,void*)) aFunction Param: (void *) PARAM { avl_walk(myTree , aFunction, NULL); } - traverse: (avl_traverser *) travPtr { id anObject; anObject = avl_traverse (myTree, travPtr) ; return anObject; } //to implement the KeyedCollection Protocol: - at: aKey { void * value=avl_find(myTree, aKey); return value; } - removeKey: aKey { return avl_delete(myTree, aKey); } - (BOOL) containsKey: aKey { if (avl_find(myTree, aKey)) return YES; else return NO; } - createIndex: (id )aZone fromMember: anObject { raiseEvent(WarningMessage,"Not Implemented"); return self; } @end @interface Agent: CreateDrop { id population; unsigned personalNumber; } + create: (id )aZone setPopulation: (id )thePopulation setPIN: (unsigned)pin; - print; - (int) getPIN; @end @implementation Agent + create: (id )aZone setPopulation: (id )thePopulation setPIN: (unsigned)pin { Agent *obj = [self createBegin: aZone]; obj->population = thePopulation; obj->personalNumber = pin; return [obj createEnd]; } - print { printf("Hello, from Agent %d \n",personalNumber); return self; } - (int) getPIN { return personalNumber; } @end @interface ModelSwarm: Swarm { id population; id myTree1; id myTree2; } - buildObjects; @end @implementation ModelSwarm //here is a user-specified comparison function. Note 3 args! static int compare_agent_position (const void *A, const void *B, void *PARAM) { int a = [(const id) A getPIN]; int b = [(const id) B getPIN]; if (a < b ) return -1; return a> b; } static void print_node ( void *A, void *PARAM) { id a = (id) A; [a print]; } - buildObjects { unsigned i; id anAgent; [super buildObjects]; population = [Array create: globalZone setCount: COUNT]; myTree1 = [[AVLSet createBegin: self ] createEnd]; myTree2 = [[AVLSet createBegin: compare_agent_position Param: NULL Zone: self ] createEnd] ; //[AVLtree create for (i = 0; i < COUNT; i++) { anAgent= [Agent create: self setPopulation: population setPIN: i]; [population atOffset: i put: anAgent]; [myTree1 add: anAgent];//uses integer keys; [myTree2 add: anAgent];//retrieves node or inserts if key not in tree already } //this amounts to a "set" return self; } - (void)test { int i; // int j; id anAgent=nil; avl_traverser trav = {0}; printf("Now, use the avl_walk to march through the tree1\n"); printf("This is supposed to start with the smallest key and move on up.\n"); [myTree1 walk: print_node Param: NULL]; anAgent = nil; printf("Now, go forwards through the tree1 with a for loop that uses \n"); printf("avl_find with the value of the agent itself from [population atOffset:i] as the key \n"); for (i = 0; i< COUNT; i++) { id outputAgent=nil; anAgent = [population atOffset: i]; outputAgent= [myTree1 at: anAgent]; [outputAgent print]; } printf("Now, go backwards through the tree2 with a for loop that uses \n"); printf("avl_find with the value of the agent itself as the key \n"); for (i = 0; i< COUNT; i++) { id outputAgent = nil; anAgent = [population atOffset: COUNT-i-1]; outputAgent = [myTree2 at: anAgent]; [outputAgent print]; } anAgent = nil; printf("Now, grab the agent 5th from the tree2 by asking for it by name \n"); anAgent = [myTree2 at: [population atOffset: 4]]; [anAgent print]; printf ("Now, grab the agent 5th (index value=4) from the tree1 by asking for it by name \n"); anAgent=nil; anAgent = [myTree1 at: [population atOffset: 4]]; [anAgent print]; printf (" Now delete the 5th agent from the tree1 and walk it\n"); [myTree1 removeKey: [population atOffset: 4]]; [myTree1 walk: print_node Param: NULL]; printf ("Observe that the 5th object still exists \n"); printf ("but it is no longer pointed to by an element in the AVLtree \n"); printf ("What happens if you drop an agent before removing it from the tree? \n"); printf ("Go into the source code and uncomment the next 3 lines after this \n"); printf ("comment if you want to see a segmentation violation \n"); //printf ("lets drop the 6th agent, then do the walk\n"); //[[population atOffset: 5] drop]; //[myTree1 walk: print_node Param: NULL]; anAgent = nil; printf("traverse \n"); while ( (anAgent=[myTree1 traverse: &trav]) != NULL) [anAgent print]; } @end int main (int argc, const char **argv) { initSwarmBatch (argc, argv); { id modelSwarm = [ModelSwarm create: globalZone]; [modelSwarm buildObjects]; [modelSwarm test]; } return 0; } /* Local Variables: compile-command: "$SWARMHOME/bin/libtool-swarm --mode=link gcc -D_GNU_SOURCE \ -DAPPNAME=avlusage2 -o avlusage2 -Wall -Werror -g -Wno-import -I$SWARMHOME/include \ -I$SWARMHOME/include/swarm -L$SWARMHOME/lib/swarm avlusage2.m -lswarm -lobjc" End: */