// typetag: "ss" (inlet, outlet) const Value Planet::link(const Value &val) { // std::cout << "link: " << val << std::endl; if (val.is_nil()) { return create_pending_links(); } Value error; Object *source = object_at(Url(val[0].str()), &error); if (error.is_error() || !object_at(Url(val[2].str()), &error)) { // not found if (val[1].str() == "=>") { return add_pending_link(val); } else if (val[1].str() == "||") { // remove from pending links return remove_pending_link(val); } return val; } Slot *slot = TYPE_CAST(Slot, source); Object *object; if (slot != NULL) { return val[1].str() == "||" ? slot->unlink(val[2]) : slot->link(val[2]); } else if ( (object = source->child("out")) && (object = object->first_child()) ) { // was a link default slots: /met/out --> /counter/in if ( (slot = TYPE_CAST(Slot, object)) ) { return val[1].str() == "||" ? slot->unlink(val[2]) : slot->link(val[2]); } else { return Value(BAD_REQUEST_ERROR, std::string("Object at '").append(slot->url()).append("' does not support links (using first child of '").append(source->url()).append("').")); } } else { return Value(BAD_REQUEST_ERROR, std::string("Object at '").append(source->url()).append("' does not support links (not an Outlet, Inlet or Node).")); } }
PROTECTED RETCODE MemReleaseBlock (void * data, Dword numBytes) { PMEMBLOCK MemBlock = MemHead->MemBlocks; // Current memory block PMEMBLOCK DataBlock = (PMEMBLOCK) data; // Block of data to release PMEMBLOCK PrevBlock = NULL; // Previous block DataBlock->Size = numBytes; // Set size of block to release into memory if (MemHead->MemBlocks < DataBlock) // Check whether block is beyond main memory block { while (MemBlock < DataBlock) // Search through memory blocks via pointer arithmetic { PrevBlock = MemBlock; // Set previous block MemBlock = MemBlock->Next; // Set current block } } else // Check for other cases { MemBlock = MemHead->MemBlocks;// Grab main memory block MemHead->MemBlocks = DataBlock; // Point main memory block to data block } MemCollectBytes (numBytes); // Collect memory from the memory block if ((PMEMBLOCK) (TYPE_CAST(Pbyte,DataBlock) + DataBlock->Size) == MemBlock) // Check whether data block may join with upper memory block { DataBlock->Size += MemBlock->Size; // Increment data block size by size of upper block DataBlock->Next = MemBlock->Next; // Point Next field of data block beyond upper block } else { DataBlock->Next = MemBlock; // Bind data block ahad to memory block } if (PrevBlock) // Check whether a previous block exists { if ((PMEMBLOCK) (TYPE_CAST(Pbyte,PrevBlock) + PrevBlock->Size) == DataBlock) // Check whether lower memory block may join with data block { PrevBlock->Size += DataBlock->Size; // Increment lower block size by size of data block PrevBlock->Next = DataBlock->Next; // Point Next field of lower block beyond data block } else PrevBlock->Next = DataBlock; // Bind previous block to data block } return RETCODE_SUCCESS; // Return success }
PROTECTED void * MemGrabBlock (Dword numBytes) { PMEMBLOCK MemBlock = MemHead->MemBlocks; // Current memory block PMEMBLOCK PrevBlock = NULL; // Previous memory block PMEMBLOCK DataBlock = NULL; // Data block Dword Size; // Size container while (MemBlock) // Check that MemBlock is not yet null { PrevBlock = MemBlock; // Set current block as previous block if (MemBlock->Size >= numBytes) // Check whether block is of at least requested capacity break; // Break out of loop MemBlock = MemBlock->Next; // Grab next block in sequence } MemAllotBytes (numBytes); // Allot memory for the memory block DataBlock = MemBlock; // Set MemBlock to DataBlock Size = MemBlock->Size - numBytes; // Figure size difference between block size and requested bytes if (MemBlock == MemHead->MemBlocks) // Check whether memory is being requested from main block { MemHead->MemBlocks = (PMEMBLOCK) (TYPE_CAST(Pbyte,MemBlock) + numBytes);// Point main block beyond requested block MemBlock = MemHead->MemBlocks; // Grab main memory block } else { MemBlock = (PMEMBLOCK) (TYPE_CAST(Pbyte,DataBlock) + numBytes); // Point MemBlock to new location PrevBlock->Next = MemBlock; // Point previous block ahead beyond data block } if (Size != 0) // Check whether difference is nonzero { MemBlock->Size = Size; // Set new memory block size MemBlock->Next = DataBlock->Next; // Point memory block ahead to next block } ZeroMemory(DataBlock,numBytes); // Set all bytes in data block to 0 return (void *) DataBlock; // Return pointer to data block }
const Value Slot::change_link(unsigned char operation, const Value &val) { if (val.is_string()) { // update a link (create/destroy) Object * target = root_->object_at(val.str()); if (!target) return ErrorValue(NOT_FOUND_ERROR, val.str()); if (!target->kind_of(Slot)) { target = target->child("in"); if (target) target = target->first_child(); // target/out/... if (!target) { return ErrorValue(NOT_FOUND_ERROR, val.str()).append(": slot not found"); } } if (kind_of(Outlet)) { // other should be an Inlet target = (Slot*)TYPE_CAST(Inlet, target); } else { // other should be an Outlet target = (Slot*)TYPE_CAST(Outlet,target); } if (!target) { return ErrorValue(BAD_REQUEST_ERROR, "Could not update link with ").append(val.to_json()).append(": incompatible)."); } if (operation == 'c') { // create link if (connect((Slot*)target)) { //std::cout << "LINKED: " << url() << " with " << val << std::endl; return Value(url()).push_back("=>").push_back(target->url()); } else { return ErrorValue(BAD_REQUEST_ERROR, "Could not make the connection with (").append(val.to_json()).append(")."); } } else { // disconnect disconnect((Slot*)target); return Value(url()).push_back("||").push_back(target->url()); } } else { return Value(info()); } }
void ObjectProxy::adopted() { root_proxy_ = TYPE_CAST(RootProxy, root_); if (root_proxy_ && type().is_nil()) { // try to find type root_proxy_->send_to_remote(ATTRS_PATH, Value(url())); } else if (value_.is_empty()) { // only get initial value if type is already there (or we won't receive the value). set_value(gNilValue); } }
const Value Planet::inspect(const Value &val) { std::cout << "## inspect " << val << "\n"; if (!val.is_string()) return Value(BAD_REQUEST_ERROR, "Bad arguments:'inspect' should be called with an url."); Value res; Object *object = find_or_build_object_at(val.str(), &res); if (!object) return res; Node *node = TYPE_CAST(Node, object); if (!node) return Value(BAD_REQUEST_ERROR, std::string("Bad target '").append(object->url()).append("':inspect only works on Nodes (class is '").append(object->class_path()).append("').")); return node->do_inspect(); }
// for help to create a portable version of this load function, read Ruby's dln.c file. bool ClassFinder::load(const char * file, const char * init_name) { void *image; void (*function)(Planet*); const char *error = 0; // load shared extension image into memory // ---> if ((image = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == 0) { printf("Could not open file '%s'.", file); if ( (error = dlerror()) ) printf(" %s\n", error); else printf("\n"); return false; } // get 'init' function into the image function = (void(*)(Planet*))dlsym(image, init_name); if (function == 0) { dlclose(image); printf("Symbol '%s' not found in '%s'.",init_name,file); if ( (error = dlerror()) ) printf(" %s\n", error); else printf("\n"); return false; } Planet *planet = TYPE_CAST(Planet, root_); // call 'init', passing planet if (planet) { (*function)(planet); } else { fprintf(stderr, "Could not cast root_ to Planet* !\n"); return false; } return true; }