/** * This file is part of Erjang - A JVM-based Erlang VM * * Copyright (c) 2009 by Trifork * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package erjang; import kilim.Pausable; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicInteger; /** * */ public class ELocalNode extends EAbstractNode { private int serial = 0; private int pidCount = 1; private int portCount = 1; private int refId[]; protected ELocalNode() { super(); init(); } /** * Create a node with the given name and the default cookie. */ protected ELocalNode(final EAtom node) { super(node); init(); } /** * Create a node with the given name and cookie. */ protected ELocalNode(final EAtom node, final EAtom cookie) { super(node, cookie); init(); } private void init() { serial = 0; pidCount = 1; portCount = 1; refId = new int[3]; refId[0] = 1; refId[1] = 0; refId[2] = 0; } /** Reference serial counters are valid when low bit of * ref_serial_high is equal to high bit of ref_serial_low. */ final static AtomicLong ref_serial_low = new AtomicLong(); final static AtomicInteger ref_serial_high = new AtomicInteger(); public ERef createRef() { /* This algorithm technically has the flaw that it may break * if > 2^63 time steps pass between these two reads... * but I think we can consider that unlikely. * -- Erik Søe Sørensen */ long low = ref_serial_low.incrementAndGet(); int high = ref_serial_high.get(); // Check validity: if ((low >>> 63) != (high & 1)) { // Adjust high: ref_serial_high.compareAndSet(high, ++high); // Don't mind if we fail; that just means someone else succeeded. } // Pick 18 + 32 + 32 bits: int id1 = (int) (low & ((1 << 18) - 1)); int id2 = (int)(low >> 18); int id3 = (int)((low >> (18+32)) | (high << (63-(18+32)))); // 1 bit overlap return new ERef(node, id1, id2, id3, creation); } public synchronized int createPortID() { portCount++; if (portCount > 0xfffffff) { /* 28 bits */ portCount = 0; } return portCount; } public EObject dsig_reg_send(EInternalPID caller, EAtom name, EObject msg) throws Pausable { return ERT.send(caller.task(), name, msg); } public void dsig_demonitor(EHandle sender, ERef ref, EObject to_pid_or_name) throws Pausable { EInternalPID pid; EAtom name; if ((pid=to_pid_or_name.testInternalPID()) != null) { EProc task = pid.task(); if (task != null) task.demonitor(ref); } else if ((name=to_pid_or_name.testAtom()) != null) { EObject local = ERT.whereis(name); if ((pid=local.testInternalPID()) != null) { EProc task = pid.task(); if (task != null) task.demonitor(ref); } } } }