Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

Multidevice ASIO output plugin for WinAMP

, 13 Feb 2009 CDDL
A tiny WinAMP output DLL that uses a C++ replacement of the official ASIO SDK that supports multiple ASIO devices.
#pragma once

#include "debugMacros.hpp"


////////////////////////////////////////////////////////////////////////////////
//
//  WinHandle
//  ---------
//
//  A simple Windows HANDLE RAII wrapper.
//
// (todo) place it in an appropriate module.
//
////////////////////////////////////////////////////////////////////////////////

class WinHandle
{
public:
    WinHandle( HANDLE const handle ) : handle_( handle ) { assert( handle ); }
    ~WinHandle() { VERIFY( ::CloseHandle( handle_ ) ); }
    HANDLE operator*() const { return handle_; }

private: // non copyable.
    WinHandle( WinHandle const & );
    void operator=( WinHandle const & );

private:
    HANDLE const handle_;
};


////////////////////////////////////////////////////////////////////////////////
//
//  WinTLS
//  ------
//
//  A wrapper around the Windows TLS implementation providing the interface
// required by the TLSObject<> class.
//
////////////////////////////////////////////////////////////////////////////////

template<class T>
class WinTLS
{
public:
    WinTLS() : tlsIndex_( ::TlsAlloc() ) { assert( tlsIndex_ != TLS_OUT_OF_INDEXES ); }
    ~WinTLS() { VERIFY( ::TlsFree( tlsIndex_ ) ); }

    bool isTLSObjectSet() const { return ::TlsGetValue( tlsIndex_ ) != NULL; }
    void setTLSObject( T & object ) { VERIFY( ::TlsSetValue( tlsIndex_, &object ) ); }
    T &  getTLSObject()             { return *reinterpret_cast<T *>( ::TlsGetValue( tlsIndex_ ) ); }

private: // non copyable.
    void operator=( WinTLS const & );
    WinTLS( WinTLS const & );

private:
    DWORD const tlsIndex_;
};


////////////////////////////////////////////////////////////////////////////////
//
//  MSVCNativeTLS
//  -------------
//
//  A wrapper around the MSVC native TLS implementation providing the interface
// required by the TLSObject<> class.
//
////////////////////////////////////////////////////////////////////////////////

template<class T>
class MSVCNativeTLS
{
public:
    MSVCNativeTLS()
    {
        assert
        (
            ( &pTLSObject != NULL ) &&
            "MSVC native TLS indices not initialized, probably used from a "
            "dynamically linked DLL in which case you must use WinTLS."
        );
    }

    static bool isTLSObjectSet() { return pTLSObject != NULL; }
    static void setTLSObject( T & object ) { pTLSObject = &object; }
    static T &  getTLSObject()             { return *pTLSObject; }

private:
    __declspec( thread ) static T * pTLSObject;
};


////////////////////////////////////////////////////////////////////////////////
//
//  TLSObject
//  ---------
//
//  A template class that wraps the usual way of setting a TLS pointer to an
// object by first saving it in a global variable and then copying it to the TLS
// from the desired thread. It provides a sort-of a thread local singleton
// interface in the sense that its methods are static and provide access to only
// a single instance of T per thread.
//  Calls to setGlobal() and setThreadLocal() are synchronized (in the sense
// that after a setGlobal() call a setThreadLocal() call (which will copy the
// global value to the TLS location) must be made before the next setGlobal()
// call will be allowed to proceed/finish).
//
////////////////////////////////////////////////////////////////////////////////

template<class T>
class TLSObject
{
public:
    static bool isGlobalSet() { return pGlobalT != NULL; }

	static T * setGlobal( T & t );
    static T & getGlobal();
    static T * resetGlobal() { T * const pOldGlobalObject( pGlobalT ); pGlobalT = NULL; return pOldGlobalObject; }

    static bool isThreadLocalSet() { return tlsImpl.isTLSObjectSet(); }

	static T & setThreadLocal();
	static T & getThreadLocal();
	
	T * operator->() const { return &getThreadLocal(); }

private:
	static WinHandle globalOKEvent;

	static T * pGlobalT;
#if defined _USRDLL || defined _WINDLL
    static WinTLS<T> tlsImpl;
#else
    static MSVCNativeTLS<T> tlsImpl;
#endif
};

#include "tlsObject.inl"

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

Share

About the Author

Domagoj Šarić
Software Developer Little Endian Ltd.
Croatia Croatia
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 13 Feb 2009
Article Copyright 2009 by Domagoj Šarić
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid