--- /dev/null
+#include "handle.h"
+#include "handle_private.h"
+
+namespace Msp {
+namespace IO {
+
+Handle::Handle():
+ priv(new Private)
+{ }
+
+Handle::Handle(const Handle &other):
+ priv(new Private)
+{
+ priv->handle = other.priv->handle;
+}
+
+Handle &Handle::operator=(const Handle &other)
+{
+ priv->handle = other.priv->handle;
+ return *this;
+}
+
+Handle::~Handle()
+{
+ delete priv;
+}
+
+Handle::operator const void *() const
+{
+#ifdef WIN32
+ return priv->handle!=INVALID_HANDLE_VALUE ? this : 0;
+#else
+ return priv->handle!=-1 ? this : 0;
+#endif
+}
+
+
+Handle::Private::Private():
+#ifdef WIN32
+ handle(INVALID_HANDLE_VALUE)
+#else
+ handle(-1)
+#endif
+{ }
+
+Handle::Private &Handle::Private::operator=(H h)
+{
+ handle = h;
+ return *this;
+}
+
+} // namespace IO
+} // namespace Msp
--- /dev/null
+#ifndef MSP_IO_HANDLE_H_
+#define MSP_IO_HANDLE_H_
+
+namespace Msp {
+namespace IO {
+
+class Handle
+{
+public:
+ struct Private;
+
+private:
+ Private *priv;
+
+public:
+ Handle();
+ Handle(const Handle &);
+ Handle &operator=(const Handle &);
+ ~Handle();
+
+ Private &operator*() { return *priv; }
+ const Private &operator*() const { return *priv; }
+
+ /** This is effectively a boolean conversion, but avoids accidental
+ conversion to OS native handles. Unix-based systems use int and win32 uses
+ void *; const void * is not implicitly convertible to either. */
+ operator const void *() const;
+};
+
+} // namespace IO
+} // namespace Msp
+
+#endif
--- /dev/null
+#ifndef MSP_IO_HANDLE_PRIVATE_H_
+#define MSP_IO_HANDLE_PRIVATE_H_
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include "handle.h"
+
+namespace Msp {
+namespace IO {
+
+struct Handle::Private
+{
+#ifdef WIN32
+ typedef HANDLE H;
+#else
+ typedef int H;
+#endif
+
+ H handle;
+
+ Private();
+
+ Private &operator=(H);
+ operator H() const { return handle; }
+};
+
+} // namespace IO
+} // namespace Msp
+
+#endif