/** * Deallocate all blocks up to and including idx, but only on these conditions in order to ensure * that only a consecutive list of blocks are allocated at any time: 1. Only if our train has left * not only this block, but also all previous blocks. 2. Only if the block shall not be re-used * ahead and all block up until the block are allocated. */ protected void deallocateUpToBlock(int idx) { for (int i = 0; i <= idx; i++) { OBlock block_i = getBlockOrderAt(i).getBlock(); if (block_i.isAllocatedTo(this)) { if ((block_i.getState() & OBlock.UNOCCUPIED) != OBlock.UNOCCUPIED) { // Do not deallocate further blocks, since this one is still allocated to us and not free. return; } boolean deAllocate = true; // look ahead to see if block_i is reused in the remaining part of the route. for (int j = _idxCurrentOrder; j < _orders.size(); j++) { OBlock block_j = getBlockOrderAt(j).getBlock(); if (!block_j.isAllocatedTo(this)) { // There is an unallocated block ahead before we have found block_i is re-used. So // deallocate block_i deAllocate = true; break; } if (block_i == block_j) { // clock_i is re-used, and we have no "holes" in the string of allocated blocks before // it. So do not deallocate. deAllocate = false; break; } } if (deAllocate) { block_i.deAllocate(this); } } } }
/** * This should not be necessary, but it turns out that if three or more trains are running on a * small layout, at some point in time a deadlock will occur where more trains want to run on the * same line in the same direction, but the train behind have allocated a block ahead of the front * train. The task of this function is therefore to deallocate any such block. */ protected void ensureRouteConsecutivity() { boolean deAllocateRestOfRoute = false; for (int i = _idxCurrentOrder + 1; i < _orders.size(); i++) { log.debug(_trainName + " ensureRouteConsecutivity for loop #" + i); BlockOrder bo = getBlockOrderAt(i); OBlock block = bo.getBlock(); if (!block.isAllocatedTo(this) || (block.getState() & OBlock.OCCUPIED) != 0) { deAllocateRestOfRoute = true; } if (deAllocateRestOfRoute) { if (block.isAllocatedTo(this)) { log.info( _trainName + " deallocating " + block.getDisplayName() + " due to risk of deadlock"); block.deAllocate(this); } } } }