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.