This is America.m in view mode; [Download] [Up]
// America-- a thread safe way of dealing with the window server.... // (The threads only think they can get away with whatever they want... // but it must get sent to an instance of America [the governing object] // for approval) #import "America.h" #import <stdio.h> #import <appkit/Matrix.h> #import <appkit/TextField.h> #import <appkit/Application.h> #import <appkit/Form.h> #import <sys/message.h> static America *sf; @implementation America - fieldThread:(int)fnum { int i,max=201; fieldUpdatePkt updatePkt; static int goober; // thanks to SortingInAction for this stuff... // modifications from hell by b.bum & a.swift (it hurt bad!) updatePkt._header.msg_remote_port = updatePort; updatePkt._header.msg_simple = TRUE; // no ports or out-of-line data updatePkt._header.msg_size = sizeof(fieldUpdatePkt); updatePkt._header.msg_local_port = PORT_NULL; updatePkt._header.msg_type = MSG_TYPE_NORMAL; updatePkt._type.msg_type_name = MSG_TYPE_INTEGER_32; updatePkt._type.msg_type_size = sizeof(MSG_TYPE_INTEGER_32)*8; updatePkt._type.msg_type_number = 2; updatePkt._type.msg_type_inline = TRUE;// no out-of-line data will be passed updatePkt._type.msg_type_longform = FALSE; updatePkt._type.msg_type_deallocate = FALSE; // set the fieldNum for the messages... this is used to grab the field // with a tag of (fnum) in the update method over in the main event thread updatePkt.fieldNum=fnum; for(i=0;i<max;i++){ // only show ever fifth number-- this could be used as a tolerance as to // how often the thread REALLY wants to update the screen for those // especially heavy CPU usage times... if(!(i%5)){ updatePkt.fieldValue=i; if (SEND_SUCCESS != (goober=msg_send((msg_header_t *) &updatePkt, MSG_OPTION_NONE, 0))){ mutex_lock(printM); fprintf(stderr, "error %d\n", goober); mutex_unlock(printM); } cthread_yield(); } } return self; } // c function wrapper void thread_field(int fnum) { [sf fieldThread:fnum]; } // method to do the actual update when received on the port - updateReceived:(fieldUpdatePkt *) pkt { [fields setIntValue:pkt->fieldValue at:pkt->fieldNum]; return self; } // c function wrapper static void do_update(fieldUpdatePkt *pkt,id self) { [self updateReceived:pkt]; } // start the threads and let it rip - start:sender { int i=0; int count=5; // this is hardwired and shouldn''t be.... for(i=0;i<count;i++) cthread_detach(cthread_fork((cthread_fn_t)thread_field, (any_t)i)); return self; } - init { printM=mutex_alloc(); lockM=mutex_alloc(); sf=self; port_allocate(task_self(), &updatePort); DPSAddPort(updatePort, (DPSPortProc) do_update, sizeof(fieldUpdatePkt), (void *)self, NX_MODALRESPTHRESHOLD+1); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.