dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/14/88)
This would be part of a generic run-time library. Note that it makes no assumptions as the format of the messages. No code as yet (just comments), but I see no difficulties. I'm hoping that by taking this just a little at a time, we can come up with something that everyone will agree on. -Matt /* * PORTS.C Matthew Dillon, Public Domain. * * SHARED PORT FUNCTION SUPPORT. These very powerful functions * handle an extended port structure facility. They are completely * generic and make no assumptions as to the contents or format of * any queued messages (except that they are headed by a Message * structure). * * * port = OpenSharedPort(name, "<access>", type) * * access string: c -create it if it doesn't exit, access * it if it does (even if not currently * owned). Non-existance means "does * not exist or exists but not owned". * * u -unique (used with "c"). Qualify the * name with ".??" (some number) to create * a unique port name. The passed 'name' * variable must have enough room to hold * the qualification. * * o -OWN the port. Call fails if the port * cannot be owned immediately. The port * will be made into a PA_SIGNAL port. * This is so you do not need to make a * OwnSharedPort() call. * * NULL is returned on error. Usually occurs when "c" is * not specified and port does not exist or has no master. * * 'type' is a longword port-type field used to ensure that * the client and master are talking the same protocol. If * the port exists and 'type' doesn't match up, NULL is * returned. For instance, my system would set type to * 'SIRC', whereas Pete's may set it to 'PCMS' or something. * This way, his system doesn't get confused with mine. * (This is all assuming we use the same library support) * * If the port doesn't exist and "c" is specified, the type * is set by the argument. * * A type of (0) matches any type. This is usually not used * in conjunction with "c". * * The name actually placed in the port's ln_Name field (on * port creation) is an allocated duplicate with slight * modifications to prevent accidental access of non-extended * ports. * * type = GetPortType(port) * * Return the port type. Usually used in conjunction with * OpenSharedPort(name, "", 0) to get the type of a port. * * error = SetPortVacume(port, function) * * Set the vacume cleaner for the port. An error is returned * if the port already has a vacume cleaner. The vacume * cleaner function is called (*function)(port) under Forbid() * in the context of the last task to close the port when * there are still messages pending on the port. * * NOTE: if ((void *)())(-1L) is specified as the function, * an internal function is used which returns any queued * messages. Since we don't know the structure of the * message, we do not attempt to modify any sub-fields. * THIS IS THE DEFAULT! * * NOTE: The vacume cleaner is considered owned by somebody * if set to some real function (not NULL and not -1). * * To use this correctly, you probably want your "PutSharedMsg" * routine to pre-set the io_Error (or whatever) to an error * condition. * * error = OwnSharedPort(port, mp_SigTask, mp_Flags) * * Immediately become the owner of a port rather than a * client of the port. Fails if the port already has an owner. * * If mp_Flags == PA_SIGNAL, mp_SigTask is ignored and * your task id is used automatically. * * * (void) QueueOwnRequest(port, ior) * * Queue a request to become the owner of a port. If the * port currently has no owner, your message will immediately * be returned and you will have ownership. On return, you * MUST check the io_Error field. If < 0, the request failed * and you do NOT own the port. The IORequest must contain * the following fields set. * * io_Message.mn_Node.ln_Pri = priority for queue * io_Message.mn_ReplyPort = replyport to return message * when ownership is achieved. * io_Unit = mp_SigTask for port. can be * NULL if mp_Flags = PA_SIGNAL. * io_Flags = mp_Flags (PA_????) * io_Error = (reserved) * io_Device = (reserved) * * io_Message.mn_Node.ln_Name= (available for personal use) * io_Command = (available for personal use) * * (void) DisownSharedPort(port) * * You must currently own the port. Ownership is removed and * you become a client to the port. Additionaly, any * ownership requests made by you via QueueOwnRequest() * are returned with io_Error = -1 * * Ownership falls to the next person queued to own the * port, if anybody. * * (void) CloseSharedPort(port) * * close a port you openned. IF you own the port * DisownSharedPort() will be automatically called. Any * ownership requests made by you via QueueOwnRequest() * will be returned with io_Error = -1. * * Ownership falls to the next task in the ownership * request queue. If there is NOBODY left to own the * port, the vacume cleaner function will be called. NOTE: * you can set the vacume cleaner function to NULL if you * wish. * * If the reference count is 0 and no messages exist in * the port's queue, the port will be deallocated. If * messages remain, the port will not be deallocated. * * (void) FixPortSignal(port) * * If any requests are present on the specified port, the * owner is signaled (used to ensure the signal associated * with a port is set if requests exist). Works even if * you aren't the owner, the port isn't owned, or the * port isn't PA_SIGNAL (i.e. becomes a nop() function). * * This call will work with normal port's as well as extended * ports. */