| Home | Libraries | People | FAQ | More

## Acknowledgements, notes and links

### Notes for Windows users

#### COM Initialization

Boost.Interprocess uses the Windows COM library to implement some features and initializes it with concurrency model `COINIT_APARTMENTTHREADED`. If the COM library was already initialized by the calling thread for another concurrency model, Boost.Interprocess handles this gracefully and uses COM calls for the already initialized model. If for some reason, you want Boost.Interprocess to initialize the COM library with another model, define the macro `BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL` before including Boost.Interprocess to one of these values:

- `COINIT_APARTMENTTHREADED_BIPC`
- `COINIT_MULTITHREADED_BIPC`
- `COINIT_DISABLE_OLE1DDE_BIPC`
- `COINIT_SPEED_OVER_MEMORY_BIPC`

#### Shared memory emulation folder

Shared memory (`shared_memory_object`) is implemented in windows using memory mapped files, placed in a shared directory in the shared documents folder (`SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Common AppData`). This directory name is the last bootup time obtained via COM calls (if `BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME`) defined or searching the system log for a startup event (the default implementation), so that each bootup shared memory is created in a new folder obtaining kernel persistence shared memory.

If using `BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME`, due to COM implementation related errors, in Boost 1.48 & Boost 1.49 the bootup-time folder was dumped and files were directly created in shared documents folder, reverting to filesystem persistence shared memory. Boost 1.50 fixed those issues and recovered bootup time directory and kernel persistence. If you need to reproduce Boost 1.48 & Boost 1.49 behaviour to communicate with applications compiled with that version, comment `#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME` directive in the Windows configuration part of `boost/interprocess/detail/workaround.hpp`.

If using the default implementation, (`BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME` undefined) and the Startup Event is not found, this might be due to some buggy software that floods or erases the event log.

In any error case (shared documents folder is not defined or bootup time could not be obtained, the library throws an error. You still can use Boost.Interprocess definining your own directory as the shared directory. Just define `BOOST_INTERPROCESS_SHARED_DIR_PATH` when using the library and that path will be used to place shared memory files.

#### BOOST_USE_WINDOWS_H support

If `BOOST_USE_WINDOWS_H` is defined, <windows.h> and other windows SDK files are included, otherwise the library declares needed functions and structures to reduce the impact of including those heavy headers.

### Notes for Linux users

#### Shared memory emulation folder

On systems without POSIX shared memory support shared memory objects are implemented as memory mapped files, using a directory placed in "/tmp" that can include (if `BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME` is defined) the last bootup time (if the Os supports it). As in Windows, in any error case obtaining this directory the library throws an error . You still can use Boost.Interprocess definining your own directory as the shared directory. Just define `BOOST_INTERPROCESS_SHARED_DIR_PATH` when using the library and that path will be used to place shared memory files.

#### Overcommit

The committed address space is the total amount of virtual memory (swap or physical memory/RAM) that the kernel might have to supply if all applications decide to access all of the memory they've requested from the kernel. By default, Linux allows processes to commit more virtual memory than available in the system. If that memory is not accessed, no physical memory + swap is actually used.

The reason for this behaviour is that Linux tries to optimize memory usage on forked processes; fork() creates a full copy of the process space, but with overcommitted memory, in this new forked instance only pages which have been written to actually need to be allocated by the kernel. If applications access more memory than available, then the kernel must free memory in the hard way: the OOM (Out Of Memory)-killer picks some processes to kill in order to recover memory.

Boost.Interprocess has no way to change this behaviour and users might suffer the OOM-killer when accessing shared memory. According to the Kernel documentation, the Linux kernel supports several overcommit modes. If you need non-kill guarantees in your application, you should change this overcommit behaviour.

### Thanks to...

Many people have contributed with ideas and revisions, so this is the place to thank them:

- Thanks to all people who have shown interest in the library and have downloaded and tested the snapshots.
- Thanks to Francis Andre and Anders Hybertz for their ideas and suggestions. Many of them are not implemented yet but I hope to include them when library gets some stability.
- Thanks to Matt Doyle, Steve LoBasso, Glenn Schrader, Hiang Swee Chiang, Phil Endecott, Rene Rivera, Harold Pirtle, Paul Ryan, Shumin Wu, Michal Wozniak, Peter Johnson, Alex Ott, Shane Guillory, Steven Wooding and Kim Barrett for their bug fixes and library testing.
- Thanks to Martin Adrian who suggested the use of Interprocess framework for user defined buffers.
- Thanks to Synge Todo for his boostbook-doxygen patch to improve Interprocess documentation.
- Thanks to Olaf Krzikalla for his Intrusive library. I have taken some ideas to improve red black tree implementation from his library.
- Thanks to Daniel James for his unordered_map/set family and his help with allocators. His great unordered implementation has been a reference to design exception safe containers.
- Thanks to Howard Hinnant for his amazing help, specially explaining allocator swapping, move semantics and for developing upgradable mutex and lock transfer features.
- Thanks to Pavel Vozenilek for his continuous review process, suggestions, code and help. He is the major supporter of Interprocess library. The library has grown with his many and great advices.
- And finally, thank you to all Boosters. Long live to C++!

### Release Notes

#### Boost 1.61 Release

- Fixed bugs:
  - ( GitHub Pull #23 ( ("Fixed case sensetive for linux mingw").

#### Boost 1.60 Release

- Improved `offset_ptr` performance and removed any undefined behaviour. No special cases needed for different compilers.
- Fixed bugs:
  - ( Trac #11699 ( ("Forward declarations of std templates causes stack corruption under Visual Studio 2015").

#### Boost 1.59 Release

- Fixed bugs:
  - ( Trac #5139 ( ("Initial Stream Position in Boost.Interprocess.Vectorstream").
  - GitHub Pull #19 ("Fix exception visibility"). Thanks to Romain-Geissler.

#### Boost 1.58 Release

- Reduced some compile-time dependencies. Updated to Boost.Container changes.
- Fixed bugs:
  - GitHub Pull #13 ("haiku: we don't have XSI shared memory, so don't try to use it"). Thanks to Jessica Hamilton.

#### Boost 1.57 Release

- Removed `unique_ptr`, now forwards boost::interprocess::unique_ptr to the general purpose `boost::movelib::unique_ptr` class from Boost.Move. This implementation is closer to the standard `std::unique_ptr` implementation and it's better maintained.
- Fixed bugs:
  - Trac #10262 ("AIX 6.1 bug with variable definition hz").
  - Trac #10229 ("Compiling errors in interprocess\detail\os_file_functions.hpp").
  - Trac #10506 ("Infinite loop in create_or_open_file").
  - GitHub Pull #11 ("Compile fix for BOOST_USE_WINDOWS_H").
- Reorganized Doxygen marks to obtain a better header reference.

#### Boost 1.56 Release

- Fixed bugs:
  - Trac #9221 ("message_queue deadlock on linux").
  - Trac #9226 ("On some computers, Common Appdata is empty in registry, so boost interprocess cannot work").
  - Trac #9262 ("windows_intermodule_singleton breaks when calling a Debug dll from a Release executable").
  - Trac #9284 ("WaitForSingleObject(mutex) must handle WAIT_ABANDONED").
  - Trac #9285 ("CreateMutex returns NULL if fails").
  - Trac #9288 ("timed_wait does not check if it has expired").
  - Trac #9408 ("Android does not support XSI_SHARED_MEMORY_OBJECTS").
  - Trac #9729 ("crash on managed_external_buffer object construction").
  - Trac #9767 ("bootstamp generation causes error in case of corrupt Windows Event Log").
  - Trac #9835 ("Boost Interprocess fails to compile with Android NDK GCC 4.8, -Werror=unused-variable").
  - Trac #9911 ("get_tmp_base_dir(...) failure").
  - Trac #9946 ("ret_ptr uninitialized in init_atomic_func, fini_atomic_func").
  - Trac #10011 ("segment_manager::find( unique_instance_t* ) fails to compile").
  - Trac #10021 ("Interprocess and BOOST_USE_WINDOWS_H").
  - Trac #10230 ("No Sleep in interprocess::winapi").
  - GitHub Pull #2 ("Provide support for the Cray C++ compiler. The Cray compiler defines __GNUC__"]).
  - GitHub Pull #3 ("Fix/mingw interprocess_exception throw in file_wrapper::priv_open_or_create"]).
- ABI breaking: #9221 showed that `BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX` option of message queue, was completely broken so an ABI break was necessary to have a working implementation.
- Simplified, refactored and unified (timed_)lock code based on try_lock(). There were several bugs when handling timeout expirations.
- Changed the implementation of condition variables' destructors to allow POSIX semantics (the condition variable can be destroyed after all waiting threads have been woken up)..
- Added `BOOST_INTERPROCESS_SHARED_DIR_PATH` option to define the shared directory used to place shared memory objects when implemented as memory mapped files.
- Added support for `BOOST_USE_WINDOWS_H`. When this macro is defined Interprocess does not declare used Windows API function and types, includes all needed windows SDK headers and uses types and functions declared by the Windows SDK.
- Added `get_size` to `::boost:interprocess:windows_shared_memory`.

#### Boost 1.55 Release

- Fixed bugs #7156 ("interprocess buffer streams leak memory on construction"]). #7164 ("Two potential bugs with b::int::vector of b::i::weak_ptr"]). #7860 ("smart_ptr's yield_k and spinlock utilities can improve spinlock-based sychronization primitives"]). #8277 ("docs for named_mutex erroneously refer to interprocess_mutex"]). #8976 ("shared_ptr fails to compile if used with a scoped_allocator"]). #9008 ("conditions variables fast enough only when opening a multiprocess browser"]). #9065 ("atomic_cas32 inline assembly wrong on ppc32"]). #9073 ("Conflict names 'realloc'"]).

#### Boost 1.54 Release

- Added support for platform-specific flags to mapped_region (ticket #8030)
- Fixed bugs #7484, #7598, #7682, #7923, #7924, #7928, #7936, #8521, #8595.
- ABI breaking: Changed bootstamp function in Windows to use EventLog service start time as system bootup time. Previously used `LastBootupTime` from WMI was unstable with time synchronization and hibernation and unusable in practice. If you really need to obtain pre Boost 1.54 behaviour define `BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME` from command line or `detail/workaround.hpp`.

#### Boost 1.53 Release

- Fixed GCC -Wshadow warnings.
- Experimental multiple allocation interface improved and changed again. Still unstable.
- Replaced deprecated BOOST_NO_XXXX with newer BOOST_NO_CXX11_XXX macros.
- ABI breaking: changed node pool allocators internals for improved efficiency.
- Fixed bug #7795.

#### Boost 1.52 Release

- Added `shrink_by` and `advise` functions in `mapped_region`.
- ABI breaking: Reimplemented `message_queue` with a circular buffer index (the old behavior used an ordered array, leading to excessive copies). This should greatly increase performance but breaks ABI. Old behaviour/ABI can be used undefining macro `BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX` in `boost/interprocess/detail/workaround.hpp`
- Improved `message_queue` insertion time avoiding priority search for common cases (both array and circular buffer configurations).
- Implemented `interproces_sharable_mutex` and `interproces_condition_any`.
- Improved `offset_ptr` performance.
- Added integer overflow checks.

#### Boost 1.51 Release

- Synchronous and asynchronous flushing for `mapped_region::flush`.
- Source & ABI breaking: Removed `get_offset` method from `mapped_region` as it has no practical utility and `m_offset` member was not for anything else.
- Source & ABI breaking: Removed `flush` from `managed_shared_memory`. as it is unspecified according to POSIX: "The effect of msync() on a shared memory object or a typed memory object is unspecified" .
- Fixed bug #7152,

#### Boost 1.50 Release

- Fixed bugs #3750, #6727, #6648,
- Shared memory in windows has again kernel persistence: kernel bootstamp and WMI has received some fixes and optimizations. This causes incompatibility with Boost 1.48 and 1.49 but the user can comment `#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME` in the windows configuration part to get Boost 1.48 & Boost 1.49 behaviour.

#### Boost 1.49 Release

- Fixed bugs #6531, #6412, #6398, #6340, #6319, #6287, #6265, #6233, #6147, #6134, #6058, #6054, #5772, #5738, #5622, #5552, #5518, #4655, #4452, #4383, #4297.
- Fixed timed functions in mutex implementations to fulfill POSIX requirements: Under no circumstance shall the function fail with a timeout if the mutex can be locked immediately. The validity of the abs_timeout parameter need not be checked if the mutex can be locked immediately.

#### Boost 1.48 Release

- Fixed bugs #2796, #4031, #4251, #4452, #4895, #5077, #5120, #5123, #5230, #5197, #5287, #5294, #5306, #5308, #5392, #5409,
- Added support to customize offset_ptr and allow creating custom managed segments that might be shared between 32 and 64 bit processes.
- Shared memory in windows has again filesystem lifetime: kernel bootstamp and WMI use to get a reliable timestamp was causing a lot of trouble.

#### Boost 1.46 Release

- Fixed bugs #4557, #4979, #4907, #4895.

#### Boost 1.45 Release

- Fixed bugs #1080, #3284, #3439, #3448, #3582, #3682, #3829, #3846, #3914, #3947, #3950, #3951, #3985, #4010, #4417, #4019, #4039, #4218, #4230, #4250, #4297, #4350, #4352, #4426, #4516, #4524, #4557, #4606, #4685, #4694.
- Added support for standard rvalue reference move semantics (tested on GCC 4.5 and VC10).
- Permissions can be detailed for interprocess named resources.
- `mapped_region::flush` initiates disk flushing but does not guarantee it's completed when returns, since it is not portable.
- FreeBSD and MacOS now use posix semaphores to implement named semaphores and mutex.

#### Boost 1.41 Release

- Support for POSIX shared memory in Mac OS.
- ABI breaking: Generic `semaphore` and `named_semaphore` now implemented more efficiently with atomic operations.
- More robust file opening in Windows platforms with active Anti-virus software.

#### Boost 1.40 Release

- Windows shared memory is created in Shared Documents folder so that it can be shared between services and processes
- Fixed bugs #2967, #2973, #2992, #3138, #3166, #3205.

#### Boost 1.39 Release

- Added experimental `stable_vector` container.
- `shared_memory_object::remove` has now POSIX `unlink` semantics and `file_mapping::remove` was added to obtain POSIX `unlink` semantics with mapped files.
- Shared memory in windows has now kernel lifetime instead of filesystem lifetime: shared memory will disappear when the system reboots.
- Updated move semantics.
- Fixed bugs #2722, #2729, #2766, #1390, #2589,

#### Boost 1.38 Release

- Updated documentation to show rvalue-references funcions instead of emulation functions.
- More non-copyable classes are now movable.
- Move-constructor and assignments now leave moved object in default-constructed state instead of just swapping contents.
- Several bugfixes ( #2391, #2431, #1390, #2570, #2528.

#### Boost 1.37 Release

- Containers can be used now in recursive types.
- Added `BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION` macro option to force the use of generic emulation code for process-shared synchronization primitives instead of native POSIX functions.
- Added placement insertion members to containers
- `boost::posix_time::pos_inf` value is now handled portably for timed functions.
- Update some function parameters from `iterator` to `const_iterator` in containers to keep up with the draft of the next standard.
- Documentation fixes.

#### Boost 1.36 Release

- Added anonymous shared memory for UNIX systems.
- Fixed erroneous `void` return types from `flat_map::erase()` functions.
- Fixed missing move semantics on managed memory classes.
- Added copy_on_write and open_read_only options for shared memory and mapped file managed classes.
- ABI breaking: Added to `mapped_region` the mode used to create it.
- Corrected instantiation errors in void allocators.
- `shared_ptr` is movable and supports aliasing.

#### Boost 1.35 Release

- Added auxiliary utilities to ease the definition and construction of `shared_ptr`, `weak_ptr` and `unique_ptr`. Added explanations and examples of these smart pointers in the documentation.
- Optimized vector:
  - 1) Now works with raw pointers as much as possible when using allocators defining `pointer` as an smart pointer. This increases performance and improves compilation times.
  - 2) A bit of metaprogramming to avoid using move_iterator when the type has trivial copy constructor or assignment and improve performance.
  - 3) Changed custom algorithms with standard ones to take advantage of optimized standard algorithms.
  - 4) Removed unused code.
- ABI breaking: Containers don't derive from allocators, to avoid problems with allocators that might define virtual functions with the same names as container member functions. That would convert container functions in virtual functions and might disallow some of them if the returned type does not lead to a covariant return. Allocators are now stored as base classes of internal structs.
- Implemented `named_mutex` and `named_semaphore` with POSIX named semaphores in systems supporting that option. `named_condition` has been accordingly changed to support interoperability with `named_mutex`.
- Reduced template bloat for node and adaptive allocators extracting node implementation to a class that only depends on the memory algorithm, instead of the segment manager + node size + node number...
- Fixed bug in `mapped_region` in UNIX when mapping address was provided but the region was mapped in another address.
- Added `aligned_allocate` and `allocate_many` functions to managed memory segments.
- Improved documentation about managed memory segments.
- Boost.Interprocess containers are now documented in the Reference section.
- Correction of typos and documentation errors.
- Added `get_instance_name`, `get_instance_length` and `get_instance_type` functions to managed memory segments.
- Corrected suboptimal buffer expansion bug in `rbtree_best_fit`.
- Added iteration of named and unique objects in a segment manager.
- Fixed leak in `vector`.
- Added support for Solaris.
- Optimized `segment_manager` to avoid code bloat associated with templated instantiations.
- Fixed bug for UNIX: No slash ('/') was being added as the first character for shared memory names, leading to errors in some UNIX systems.
- Fixed bug in VC-8.0: Broken function inlining in core offset_ptr functions.
- Code examples changed to use new BoostBook code import features.
- Added aligned memory allocation function to memory algorithms.
- Fixed bug in `deque::clear()` and `deque::erase()`, they were declared private.
- Fixed bug in `deque::erase()`. Thanks to Steve LoBasso.
- Fixed bug in `atomic_dec32()`. Thanks to Glenn Schrader.
- Improved (multi)map/(multi)set constructors taking iterators. Now those have linear time if the iterator range is already sorted.
- ABI breaking: (multi)map/(multi)set now reduce their node size. The color bit is embedded in the parent pointer. Now, the size of a node is the size of 3 pointers in most systems. This optimization is activated for raw and `offset_ptr` pointers.
- (multi)map/(multi)set now reuse memory from old nodes in the assignment operator.
- ABI breaking: Implemented node-containers based on intrusive containers. This saves code size, since many instantiations share the same algorithms.
- Corrected code to be compilable with Visual C++ 8.0.
- Added function to zero free memory in memory algorithms and the segment manager. This function is useful for security reasons and to improve compression ratios for files created with `managed_mapped_file`.
- Added support for intrusive index types in managed memory segments. Intrusive indexes save extra memory allocations to allocate the index since with just one allocation, we allocate room for the value, the name and the hook to insert the object in the index.
- Created new index type: iset_index. It's an index based on an intrusive set (rb-tree).
- Created new index type: iunordered_set_index. It's an index based on a pseudo-intrusive unordered set (hash table).
- ABI breaking: The intrusive index iset_index is now the default index type.
- Optimized vector to take advantage of `boost::has_trivial_destructor`. This optimization avoids calling destructors of elements that have a trivial destructor.
- Optimized vector to take advantage of `has_trivial_destructor_after_move` trait. This optimization avoids calling destructors of elements that have a trivial destructor if the element has been moved (which is the case of many movable types). This trick was provided by Howard Hinnant.
- Added security check to avoid integer overflow bug in allocators and named construction functions.
- Added alignment checks to forward and backwards expansion functions.
- Fixed bug in atomic functions for PPC.
- Fixed race-condition error when creating and opening a managed segment.
- Added adaptive pools.
- Source breaking: Changed node allocators' template parameter order to make them easier to use.
- Added support for native windows shared memory.
- Added more tests.
- Corrected the presence of private functions in the reference section.
- Added function (`deallocate_free_chunks()`) to manually deallocate completely free chunks from node allocators.
- Implemented N1780 proposal to LWG issue 233: Insertion hints in associative containers in interprocess `multiset` and `multimap` classes.
- Source breaking: A shared memory object is now used including `shared_memory_object.hpp` header instead of `shared memory.hpp`.
- ABI breaking: Changed global mutex when initializing managed shared memory and memory mapped files. This change tries to minimize deadlocks.
- Source breaking: Changed shared memory, memory mapped files and mapped region's open mode to a single `mode_t` type.
- Added extra WIN32_LEAN_AND_MEAN before including DateTime headers to avoid socket redefinition errors when using Interprocess and Asio in windows.
- ABI breaking: `mapped_region` constructor no longer requires classes derived from memory_mappable, but classes must fulfill the MemoryMappable concept.
- Added in-place reallocation capabilities to basic_string.
- ABI breaking: Reimplemented and optimized small string optimization. The narrow string class has zero byte overhead with an internal 11 byte buffer in 32 systems!
- Added move semantics to containers. Improves performance when using containers of containers.
- ABI breaking: End nodes of node containers (list, slist, map/set) are now embedded in the containers instead of allocated using the allocator. This allows no-throw move-constructors and improves performance.
- ABI breaking: slist and list containers now have constant-time size() function. The size of the container is added as a member.

### Books and interesting links

Some useful references about the C++ programming language, C++ internals, shared memory, allocators and containers used to design Boost.Interprocess.

#### Books

- Great book about multithreading, and POSIX: "Programming with Posix Threads", David R. Butenhof
- The UNIX inter-process bible: "UNIX Network Programming, Volume 2: Interprocess Communications", W. Richard Stevens
- Current STL allocator issues: "Effective STL", Scott Meyers
- My C++ bible: "Thinking in C++, Volume 1 & 2", Bruce Eckel and Chuck Allison
- The book every C++ programmer should read: "Inside the C++ Object Model", Stanley B. Lippman
- A must-read: "ISO/IEC TR 18015: Technical Report on C++ Performance", ISO WG21-SC22 members.

#### Links

- A framework to put the STL in shared memory: "A C++ Standard Allocator for the Standard Template Library" .
- Instantiating C++ objects in shared memory: "Using objects in shared memory for C++ application" .
- A shared memory allocator and relative pointer: "Taming Shared Memory" .

### Future improvements...

There are some Interprocess features that I would like to implement and some Boost.Interprocess code that can be much better. Let's see some ideas:

#### Win32 synchronization is too basic

Win32 version of shared mutexes and shared conditions are based on "spin and wait" atomic instructions. This leads to poor performance and does not manage any issues like priority inversions. We would need very serious help from threading experts on this. And I'm not sure that this can be achieved in user-level software. Posix based implementations use PTHREAD_PROCESS_SHARED attribute to place mutexes in shared memory, so there are no such problems. I'm not aware of any implementation that simulates PTHREAD_PROCESS_SHARED attribute for Win32. We should be able to construct these primitives in memory mapped files, so that we can get filesystem persistence just like with POSIX primitives.

#### Use of wide character names on Boost.Interprocess basic resources

Currently Interprocess only allows char based names for basic named objects. However, several operating systems use wchar_t names for resources (mapped files, for example). In the future Interprocess should try to present a portable narrow/wide char interface. To do this, it would be useful to have a boost wstring <-> string conversion utilities to translate resource names (escaping needed characters that can conflict with OS names) in a portable way. It would be interesting also the use of boost::filesystem paths to avoid operating system specific issues.

#### Security attributes

Boost.Interprocess does not define security attributes for shared memory and synchronization objects. Standard C++ also ignores security attributes with files so adding security attributes would require some serious work.

#### Future inter-process communications

Boost.Interprocess offers a process-shared message queue based on Boost.Interprocess primitives like mutexes and conditions. I would want to develop more mechanisms, like stream-oriented named fifo so that we can use it with a iostream-interface wrapper (we can imitate Unix pipes).

C++ needs more complex mechanisms and it would be nice to have a stream and datagram oriented PF_UNIX-like mechanism in C++. And for very fast inter-process remote calls Solaris doors is an interesting alternative to implement for C++. But the work to implement PF_UNIX-like sockets and doors would be huge (and it might be difficult in a user-level library). Any network expert volunteer?