/**
  * Remove the channel from the channel map and free the number for re-use. This method must be
  * safe to call multiple times on the same channel. If it is not then things go badly wrong.
  */
 public void releaseChannelNumber(ChannelN channel) {
   // Warning, here be dragons. Not great big ones, but little baby ones
   // which will nibble on your toes and occasionally trip you up when
   // you least expect it. (Pixies? HP2)
   // Basically, there's a race that can end us up here. It almost never
   // happens, but it's easier to repair it when it does than prevent it
   // from happening in the first place.
   // If we end up doing a Channel.close in one thread and a Channel.open
   // with the same channel number in another, the two can overlap in such
   // a way as to cause disconnectChannel on the old channel to try to
   // remove the new one. Ideally we would fix this race at the source,
   // but it's much easier to just catch it here.
   synchronized (this.monitor) {
     int channelNumber = channel.getChannelNumber();
     ChannelN existing = _channelMap.remove(channelNumber);
     // Nothing to do here. Move along.
     if (existing == null) return;
     // Oops, we've gone and stomped on someone else's channel. Put it
     // back and pretend we didn't touch it.
     else if (existing != channel) {
       _channelMap.put(channelNumber, existing);
       return;
     }
     channelNumberAllocator.free(channelNumber);
   }
 }
 public ChannelN createChannel(AMQConnection connection, int channelNumber) throws IOException {
   ChannelN ch;
   synchronized (this.monitor) {
     if (channelNumberAllocator.reserve(channelNumber)) {
       ch = addNewChannel(connection, channelNumber);
     } else {
       return null;
     }
   }
   ch.open(); // now that it's been safely added
   return ch;
 }