<commit_before>// TestWin32.cpp : Definiert den Einsprungpunkt fr die Anwendung.
//

#define _WIN32_DCOM

#include "stdafx.h"

#include <windows.h>

#include <ole2.h>
#include <objidl.h>
#include <objbase.h>
#include <process.h>
#include <olectl.h>
#include <stdlib.h>
#include <malloc.h>
#include <..\..\inc\systools\win32\MtaOleClipb.h>

#include "resource.h"

#define MAX_LOADSTRING 100

// Globale Variablen:
HINSTANCE           hInst;                      // aktuelle Instanz
WCHAR               szTitle[MAX_LOADSTRING];            // Text der Titelzeile
WCHAR               szWindowClass[MAX_LOADSTRING];  // Text der Titelzeile
ATOM                MyRegisterClass( HINSTANCE hInstance );
BOOL                InitInstance( HINSTANCE, int );
LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );
LRESULT CALLBACK    About( HWND, UINT, WPARAM, LPARAM );
void                PasteClipboardData(HWND hwndParent);
void                PasteClipboardData2(HWND hwndParent);

LPSTREAM            g_pStm    = NULL;
char*               pTextBuff = NULL;
DWORD               lData     = 0;

//----------------------------------------------------
// a thread function
//----------------------------------------------------

unsigned int _stdcall ThreadProc(LPVOID pParam)
{
    IDataObject* pIDataObj = NULL;
    FORMATETC    formatETC;
    STGMEDIUM    stgMedium;
    LPVOID       pGlobMem;
    HWND         hwnd;
    DWORD        sizeGlobBuff;
    HRESULT      hr;

    hwnd = (HWND)pParam;

    OleInitialize( NULL );

    hr = OleGetClipboard( &pIDataObj );

    hr = CoGetInterfaceAndReleaseStream(
        g_pStm,
        __uuidof(IDataObject),
        reinterpret_cast<LPVOID*>(&pIDataObj));

    formatETC.cfFormat = CF_TEXT;
    formatETC.ptd      = NULL;
    formatETC.dwAspect = DVASPECT_CONTENT;
    formatETC.lindex   = -1;
    formatETC.tymed    = TYMED_HGLOBAL;

    hr = pIDataObj->GetData( &formatETC, &stgMedium );
    pGlobMem = GlobalLock( stgMedium.hGlobal );
    if ( NULL != pGlobMem )
    {
        if ( NULL != pTextBuff )
        {
            free( pTextBuff );
        }

        sizeGlobBuff = GlobalSize( stgMedium.hGlobal );
        pTextBuff = (char*)malloc( sizeGlobBuff + 1 );
        ZeroMemory( pTextBuff, sizeGlobBuff + 1 );

        memcpy( pTextBuff, pGlobMem, sizeGlobBuff );
        lData = sizeGlobBuff;

        InvalidateRect( hwnd, NULL, TRUE );
        UpdateWindow( hwnd );
    }

    GlobalUnlock( stgMedium.hGlobal );

    ReleaseStgMedium( &stgMedium );

    pIDataObj->Release();

    //CoUninitialize( );

    OleUninitialize( );

    return 0;
}

//----------------------------------------------------
// WinMain
//----------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
     // ZU ERLEDIGEN: Fgen Sie hier den Code ein.
    MSG     msg;
    HACCEL  hAccelTable;
    HRESULT hr = E_FAIL;

    // it's important to initialize ole
    // in order to use the clipboard
    //hr = OleInitialize( NULL );
    hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
    //hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );

    // Globale Zeichenfolgen initialisieren
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_TESTWIN32, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Initialisierung der Anwendung durchfhren:
    if( !InitInstance( hInstance, nCmdShow ) )
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TESTWIN32);

    // Hauptnachrichtenschleife:
    while( GetMessage(&msg, NULL, 0, 0) )
    {
        if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }

    // uninitializing the ole libraries
    //OleUninitialize( );
    CoUninitialize( );

    return msg.wParam;
}

//
//  FUNKTION: MyRegisterClass()
//
//  AUFGABE: Registriert die Fensterklasse.
//
//  KOMMENTARE:
//
//    Diese Funktion und ihre Verwendung sind nur notwendig, wenn dieser Code
//    mit Win32-Systemen vor der 'RegisterClassEx'-Funktion kompatibel sein soll,
//    die zu Windows 95 hinzugefgt wurde. Es ist wichtig diese Funktion aufzurufen,
//    damit der Anwendung kleine Symbole mit den richtigen Proportionen zugewiesen
//    werden.
//
ATOM MyRegisterClass( HINSTANCE hInstance )
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, (LPCTSTR)IDI_TESTWIN32);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = (LPCWSTR)IDC_TESTWIN32;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

    return RegisterClassExW(&wcex);
}

//
//   FUNKTION: InitInstance(HANDLE, int)
//
//   AUFGABE: Speichert die Instanzzugriffsnummer und erstellt das Hauptfenster
//
//   KOMMENTARE:
//
//        In dieser Funktion wird die Instanzzugriffsnummer in einer globalen Variable
//        gespeichert und das Hauptprogrammfenster erstellt und angezeigt.
//
BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
{
   HWND hWnd;

   hInst = hInstance; // Instanzzugriffsnummer in unserer globalen Variable speichern

   hWnd = CreateWindowExW(0, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if( !hWnd )
   {
      return FALSE;
   }

   ShowWindow( hWnd, nCmdShow );
   UpdateWindow( hWnd );

   return TRUE;
}

//
//  FUNKTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  AUFGABE:  Verarbeitet Nachrichten fr das Hauptfenster.
//
//  WM_COMMAND  - Anwendungsmen verarbeiten
//  WM_PAINT    - Hauptfenster darstellen
//  WM_DESTROY  - Beendigungsnachricht ausgeben und zurckkehren
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int         wmId;
    int         wmEvent;
    PAINTSTRUCT ps;
    HDC         hdc;
    TCHAR       szHello[MAX_LOADSTRING];

    LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

    switch( message )
    {
        case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Menauswahlen analysieren:
            switch( wmId )
            {
                case IDD_PASTE:
                    //PasteClipboardData(hWnd);
                    PasteClipboardData2(hWnd);
                    break;

                case IDM_EXIT:
                   DestroyWindow( hWnd );
                   break;

                default:
                   return DefWindowProc( hWnd, message, wParam, lParam );
            }
            break;

        case WM_PAINT:
            hdc = BeginPaint (hWnd, &ps);
            // ZU ERLEDIGEN: Hier beliebigen Code zum Zeichnen hinzufgen...
            RECT rt;
            GetClientRect( hWnd, &rt );

            if ( NULL != pTextBuff )
            {
                DrawText( hdc, pTextBuff, lData, &rt, DT_CENTER );
            }
            else
            {
                DrawText( hdc, szHello, strlen(szHello), &rt, DT_CENTER );
            }

            EndPaint( hWnd, &ps );
            break;

        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;

        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
   }
   return 0;
}

void PasteClipboardData2(HWND hwndParent)
{
    IDataObject* pIDataObject;
    HRESULT      hr;
    FORMATETC    formatETC;
    STGMEDIUM    stgMedium;
    LPVOID       pGlobMem;
    HWND         hwnd;
    DWORD        sizeGlobBuff;

    hr = MTAGetClipboard( &pIDataObject );
    if ( SUCCEEDED( hr ) )
    {
        formatETC.cfFormat = CF_TEXT;
        formatETC.ptd      = NULL;
        formatETC.dwAspect = DVASPECT_CONTENT;
        formatETC.lindex   = -1;
        formatETC.tymed    = TYMED_HGLOBAL;

        hr = pIDataObject->GetData( &formatETC, &stgMedium );
        pGlobMem = GlobalLock( stgMedium.hGlobal );
        if ( NULL != pGlobMem )
        {
            if ( NULL != pTextBuff )
            {
                free( pTextBuff );
            }

            sizeGlobBuff = GlobalSize( stgMedium.hGlobal );
            pTextBuff = (char*)malloc( sizeGlobBuff + 1 );
            ZeroMemory( pTextBuff, sizeGlobBuff + 1 );

            memcpy( pTextBuff, pGlobMem, sizeGlobBuff );
            lData = sizeGlobBuff;

            InvalidateRect( hwndParent, NULL, TRUE );
            UpdateWindow( hwndParent );
        }

        GlobalUnlock( stgMedium.hGlobal );

        ReleaseStgMedium( &stgMedium );

        pIDataObject->Release();
    }
}

//----------------------------------------------------
// clipboard handling
//----------------------------------------------------

/*
void PasteClipboardData(HWND hwndParent)
{
    IDataObject* pIDataObj = NULL;
    HRESULT      hr        = E_FAIL;
    unsigned int dwId;

    hr = OleGetClipboard( &pIDataObj );
    if ( SUCCEEDED( hr ) )
    {
        HRESULT hr = CoMarshalInterThreadInterfaceInStream(
            __uuidof(IDataObject), //The IID of inteface to be marshaled
            pIDataObj,       //The interface pointer
            &g_pStm          //IStream pointer
            );

        HANDLE hThread = (HANDLE)_beginthreadex(
                NULL,       //Security
                0,          //Stack Size
                ThreadProc, //Start Address
                NULL,       //Parmeter
                (unsigned int)hwndParent,   //Creation Flag
                &dwId       //Thread Id
                );

        //Wait for the thread to finish execution
        //A thread handle is signaled is thread execution
        //is complete
        for(;;)
        {
            DWORD dwRet = ::MsgWaitForMultipleObjects(
                                    1,          //Count of objects
                                    &hThread,   //pointer to the array of objects
                                    FALSE,      //Wait for all objects?
                                    INFINITE,   //Wait How Long?
                                    QS_ALLINPUT //Wait for all messges
                                    );

            //This means that the object is signaled
            if ( dwRet != WAIT_OBJECT_0 + 1 )
                break;

            //Remove the messages from the queue
            MSG msg;

            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
            {
                //Not essential
                TranslateMessage(&msg);
                //Let the windowproc handle the message
                DispatchMessage(&msg);
            }
        }

        CloseHandle( hThread );
        pIDataObj->Release();
    }
}
*/
<commit_msg>INTEGRATION: CWS pchfix02 (1.1.600); FILE MERGED 2006/09/01 17:34:23 kaib 1.1.600.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cbptest.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 09:11:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"
// TestWin32.cpp : Definiert den Einsprungpunkt fr die Anwendung.
//

#define _WIN32_DCOM

#include "stdafx.h"

#include <windows.h>

#include <ole2.h>
#include <objidl.h>
#include <objbase.h>
#include <process.h>
#include <olectl.h>
#include <stdlib.h>
#include <malloc.h>
#include <..\..\inc\systools\win32\MtaOleClipb.h>

#include "resource.h"

#define MAX_LOADSTRING 100

// Globale Variablen:
HINSTANCE           hInst;                      // aktuelle Instanz
WCHAR               szTitle[MAX_LOADSTRING];            // Text der Titelzeile
WCHAR               szWindowClass[MAX_LOADSTRING];  // Text der Titelzeile
ATOM                MyRegisterClass( HINSTANCE hInstance );
BOOL                InitInstance( HINSTANCE, int );
LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );
LRESULT CALLBACK    About( HWND, UINT, WPARAM, LPARAM );
void                PasteClipboardData(HWND hwndParent);
void                PasteClipboardData2(HWND hwndParent);

LPSTREAM            g_pStm    = NULL;
char*               pTextBuff = NULL;
DWORD               lData     = 0;

//----------------------------------------------------
// a thread function
//----------------------------------------------------

unsigned int _stdcall ThreadProc(LPVOID pParam)
{
    IDataObject* pIDataObj = NULL;
    FORMATETC    formatETC;
    STGMEDIUM    stgMedium;
    LPVOID       pGlobMem;
    HWND         hwnd;
    DWORD        sizeGlobBuff;
    HRESULT      hr;

    hwnd = (HWND)pParam;

    OleInitialize( NULL );

    hr = OleGetClipboard( &pIDataObj );

    hr = CoGetInterfaceAndReleaseStream(
        g_pStm,
        __uuidof(IDataObject),
        reinterpret_cast<LPVOID*>(&pIDataObj));

    formatETC.cfFormat = CF_TEXT;
    formatETC.ptd      = NULL;
    formatETC.dwAspect = DVASPECT_CONTENT;
    formatETC.lindex   = -1;
    formatETC.tymed    = TYMED_HGLOBAL;

    hr = pIDataObj->GetData( &formatETC, &stgMedium );
    pGlobMem = GlobalLock( stgMedium.hGlobal );
    if ( NULL != pGlobMem )
    {
        if ( NULL != pTextBuff )
        {
            free( pTextBuff );
        }

        sizeGlobBuff = GlobalSize( stgMedium.hGlobal );
        pTextBuff = (char*)malloc( sizeGlobBuff + 1 );
        ZeroMemory( pTextBuff, sizeGlobBuff + 1 );

        memcpy( pTextBuff, pGlobMem, sizeGlobBuff );
        lData = sizeGlobBuff;

        InvalidateRect( hwnd, NULL, TRUE );
        UpdateWindow( hwnd );
    }

    GlobalUnlock( stgMedium.hGlobal );

    ReleaseStgMedium( &stgMedium );

    pIDataObj->Release();

    //CoUninitialize( );

    OleUninitialize( );

    return 0;
}

//----------------------------------------------------
// WinMain
//----------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
     // ZU ERLEDIGEN: Fgen Sie hier den Code ein.
    MSG     msg;
    HACCEL  hAccelTable;
    HRESULT hr = E_FAIL;

    // it's important to initialize ole
    // in order to use the clipboard
    //hr = OleInitialize( NULL );
    hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
    //hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );

    // Globale Zeichenfolgen initialisieren
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_TESTWIN32, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Initialisierung der Anwendung durchfhren:
    if( !InitInstance( hInstance, nCmdShow ) )
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TESTWIN32);

    // Hauptnachrichtenschleife:
    while( GetMessage(&msg, NULL, 0, 0) )
    {
        if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }

    // uninitializing the ole libraries
    //OleUninitialize( );
    CoUninitialize( );

    return msg.wParam;
}

//
//  FUNKTION: MyRegisterClass()
//
//  AUFGABE: Registriert die Fensterklasse.
//
//  KOMMENTARE:
//
//    Diese Funktion und ihre Verwendung sind nur notwendig, wenn dieser Code
//    mit Win32-Systemen vor der 'RegisterClassEx'-Funktion kompatibel sein soll,
//    die zu Windows 95 hinzugefgt wurde. Es ist wichtig diese Funktion aufzurufen,
//    damit der Anwendung kleine Symbole mit den richtigen Proportionen zugewiesen
//    werden.
//
ATOM MyRegisterClass( HINSTANCE hInstance )
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, (LPCTSTR)IDI_TESTWIN32);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = (LPCWSTR)IDC_TESTWIN32;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

    return RegisterClassExW(&wcex);
}

//
//   FUNKTION: InitInstance(HANDLE, int)
//
//   AUFGABE: Speichert die Instanzzugriffsnummer und erstellt das Hauptfenster
//
//   KOMMENTARE:
//
//        In dieser Funktion wird die Instanzzugriffsnummer in einer globalen Variable
//        gespeichert und das Hauptprogrammfenster erstellt und angezeigt.
//
BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
{
   HWND hWnd;

   hInst = hInstance; // Instanzzugriffsnummer in unserer globalen Variable speichern

   hWnd = CreateWindowExW(0, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if( !hWnd )
   {
      return FALSE;
   }

   ShowWindow( hWnd, nCmdShow );
   UpdateWindow( hWnd );

   return TRUE;
}

//
//  FUNKTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  AUFGABE:  Verarbeitet Nachrichten fr das Hauptfenster.
//
//  WM_COMMAND  - Anwendungsmen verarbeiten
//  WM_PAINT    - Hauptfenster darstellen
//  WM_DESTROY  - Beendigungsnachricht ausgeben und zurckkehren
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int         wmId;
    int         wmEvent;
    PAINTSTRUCT ps;
    HDC         hdc;
    TCHAR       szHello[MAX_LOADSTRING];

    LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

    switch( message )
    {
        case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Menauswahlen analysieren:
            switch( wmId )
            {
                case IDD_PASTE:
                    //PasteClipboardData(hWnd);
                    PasteClipboardData2(hWnd);
                    break;

                case IDM_EXIT:
                   DestroyWindow( hWnd );
                   break;

                default:
                   return DefWindowProc( hWnd, message, wParam, lParam );
            }
            break;

        case WM_PAINT:
            hdc = BeginPaint (hWnd, &ps);
            // ZU ERLEDIGEN: Hier beliebigen Code zum Zeichnen hinzufgen...
            RECT rt;
            GetClientRect( hWnd, &rt );

            if ( NULL != pTextBuff )
            {
                DrawText( hdc, pTextBuff, lData, &rt, DT_CENTER );
            }
            else
            {
                DrawText( hdc, szHello, strlen(szHello), &rt, DT_CENTER );
            }

            EndPaint( hWnd, &ps );
            break;

        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;

        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
   }
   return 0;
}

void PasteClipboardData2(HWND hwndParent)
{
    IDataObject* pIDataObject;
    HRESULT      hr;
    FORMATETC    formatETC;
    STGMEDIUM    stgMedium;
    LPVOID       pGlobMem;
    HWND         hwnd;
    DWORD        sizeGlobBuff;

    hr = MTAGetClipboard( &pIDataObject );
    if ( SUCCEEDED( hr ) )
    {
        formatETC.cfFormat = CF_TEXT;
        formatETC.ptd      = NULL;
        formatETC.dwAspect = DVASPECT_CONTENT;
        formatETC.lindex   = -1;
        formatETC.tymed    = TYMED_HGLOBAL;

        hr = pIDataObject->GetData( &formatETC, &stgMedium );
        pGlobMem = GlobalLock( stgMedium.hGlobal );
        if ( NULL != pGlobMem )
        {
            if ( NULL != pTextBuff )
            {
                free( pTextBuff );
            }

            sizeGlobBuff = GlobalSize( stgMedium.hGlobal );
            pTextBuff = (char*)malloc( sizeGlobBuff + 1 );
            ZeroMemory( pTextBuff, sizeGlobBuff + 1 );

            memcpy( pTextBuff, pGlobMem, sizeGlobBuff );
            lData = sizeGlobBuff;

            InvalidateRect( hwndParent, NULL, TRUE );
            UpdateWindow( hwndParent );
        }

        GlobalUnlock( stgMedium.hGlobal );

        ReleaseStgMedium( &stgMedium );

        pIDataObject->Release();
    }
}

//----------------------------------------------------
// clipboard handling
//----------------------------------------------------

/*
void PasteClipboardData(HWND hwndParent)
{
    IDataObject* pIDataObj = NULL;
    HRESULT      hr        = E_FAIL;
    unsigned int dwId;

    hr = OleGetClipboard( &pIDataObj );
    if ( SUCCEEDED( hr ) )
    {
        HRESULT hr = CoMarshalInterThreadInterfaceInStream(
            __uuidof(IDataObject), //The IID of inteface to be marshaled
            pIDataObj,       //The interface pointer
            &g_pStm          //IStream pointer
            );

        HANDLE hThread = (HANDLE)_beginthreadex(
                NULL,       //Security
                0,          //Stack Size
                ThreadProc, //Start Address
                NULL,       //Parmeter
                (unsigned int)hwndParent,   //Creation Flag
                &dwId       //Thread Id
                );

        //Wait for the thread to finish execution
        //A thread handle is signaled is thread execution
        //is complete
        for(;;)
        {
            DWORD dwRet = ::MsgWaitForMultipleObjects(
                                    1,          //Count of objects
                                    &hThread,   //pointer to the array of objects
                                    FALSE,      //Wait for all objects?
                                    INFINITE,   //Wait How Long?
                                    QS_ALLINPUT //Wait for all messges
                                    );

            //This means that the object is signaled
            if ( dwRet != WAIT_OBJECT_0 + 1 )
                break;

            //Remove the messages from the queue
            MSG msg;

            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
            {
                //Not essential
                TranslateMessage(&msg);
                //Let the windowproc handle the message
                DispatchMessage(&msg);
            }
        }

        CloseHandle( hThread );
        pIDataObj->Release();
    }
}
*/
<|endoftext|>


<commit_before>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QPixmap>
#include <QPushButton>
#include <QtTest/QtTest>
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include "busywidget.h"
#include "confirmationdialog.h"
#include "elidedannotatedlabel.h"
#include "filepickerdialog.h"
#include "filepickerwidget.h"

#include "ElidedLabel.h"
#include "TSettings.h"
#include "TWizard.h"
#include "TWizardPage.h"

class TestSmallWidgets : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void elidedLabel();
    void elidedAnnotatedLabel();
    void filepickerwidget();
    void filepickerdialog();
    void confirmationDialog();
    void busywidget();
    void statuslabel();
    void twizard();
};

void TestSmallWidgets::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    // Use a custom message handler to filter out unwanted messages
    IF_NOT_VISUAL { qInstallMessageHandler(offscreenMessageOutput); }
}

void TestSmallWidgets::cleanupTestCase()
{
    TSettings::destroy();
}

void TestSmallWidgets::elidedLabel()
{
    // Initialize variables.
    const QString text("this is a long long long piece of text");
    ElidedLabel * elidedlabel = new ElidedLabel();

    VISUAL_INIT(elidedlabel);

    // Set up ElidedText.
    elidedlabel->setElide(Qt::ElideRight);
    elidedlabel->setText(text);

    // The text should be fully visible if there's enough room.
    elidedlabel->setGeometry(100, 100, 1000, 20);
    QVERIFY(elidedlabel->text() == text);
    QVERIFY(elidedlabel->elideText(text).count() == text.count());
    VISUAL_WAIT;

    // The text should be elided if the widget is too narrow.
    elidedlabel->setGeometry(100, 100, 100, 20);
    QVERIFY(elidedlabel->text() == text);
    QVERIFY(elidedlabel->elideText(text).count() < text.count());
    VISUAL_WAIT;

    delete elidedlabel;
}

void TestSmallWidgets::elidedAnnotatedLabel()
{
    ElidedAnnotatedLabel *el = new ElidedAnnotatedLabel();

    const QString plain("grey black long piece of text again grey");
    const QString full("grey black long piece of "
                       "text again grey");
    QVector<QString> texts(3);
    texts[0] = "grey";
    texts[1] = " black long piece of text ";
    texts[2] = "again grey";
    QVector<QString> annotations(6, "");
    annotations[0] = "";
    annotations[1] = "";
    annotations[4] = "";
    annotations[5] = "";

    VISUAL_INIT(el);

    // Set up ElidedText.
    el->setElide(Qt::ElideRight);
    el->setAnnotatedText(texts, annotations);

    // The text should be fully visible if there's enough room.
    el->setGeometry(100, 100, 1000, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() == full.count());
    VISUAL_WAIT;

    // The text should be elided if the widget is too narrow.
    el->setGeometry(100, 100, 100, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() < full.count());
    VISUAL_WAIT;

    delete el;
}

void TestSmallWidgets::filepickerwidget()
{
    FilePickerWidget *fpw = new FilePickerWidget();
    delete fpw;
}

void TestSmallWidgets::filepickerdialog()
{
    QWidget *         widget = new QWidget();
    FilePickerDialog *fpd    = new FilePickerDialog(widget);

    QList<QUrl> myurls({QUrl("file:///tmp")});
    fpd->setSelectedUrls(myurls);
    QVERIFY(fpd->getSelectedUrls() == myurls);

    delete fpd;
    delete widget;
}

void TestSmallWidgets::confirmationDialog()
{
    ConfirmationDialog *confirm = new ConfirmationDialog();
    delete confirm;
}

void TestSmallWidgets::busywidget()
{
    BusyWidget *bw = new BusyWidget();

    VISUAL_INIT(bw);

    // Before starting
    VISUAL_WAIT;

    // Animation
    bw->animate(true);
    QTest::qWait(100);
    VISUAL_WAIT;

    // After animation
    bw->animate(false);
    QTest::qWait(100);
    VISUAL_WAIT;

    delete bw;
}

void TestSmallWidgets::statuslabel()
{
    ElidedLabel *el = new ElidedLabel();
    el->setMinimumWidth(200);

    VISUAL_INIT(el);

    el->messageNormal("normal message");
    VISUAL_WAIT;

    el->messageError("error message");
    VISUAL_WAIT;

    delete el;
}

void TestSmallWidgets::twizard()
{
    TWizard *wizard = new TWizard();

    // Add logo
    QPixmap pix(32, 32);
    pix.fill(Qt::blue);
    wizard->setLogo(pix);

    // Create pages with titles
    TWizardPage *p1 = new TWizardPage();
    TWizardPage *p2 = new TWizardPage();
    p1->setTitle("page 1");
    p2->setTitle("page 2");

    // Add a "proceed" button to each page
    QPushButton *pb1 = new QPushButton(p1);
    pb1->setText("Next");
    pb1->setObjectName("nextButton");
    QPushButton *pb2 = new QPushButton(p2);
    pb2->setText("Finish");
    pb2->setObjectName("finishButton");

    // Add pages to the wizard; must be after the buttons have been added
    wizard->addPages(QList<TWizardPage *>() << p1 << p2);

    // Navigate through the pages.
    VISUAL_INIT(wizard);
    IF_NOT_VISUAL { wizard->open(); }

    wizard->currentPage()->button(TWizardPage::NextButton)->click();
    VISUAL_WAIT;
    wizard->currentPage()->button(TWizardPage::FinishButton)->click();
    VISUAL_WAIT;

    // We should have quit the wizard
    QVERIFY(wizard->isVisible() == false);

    delete wizard;
}

QTEST_MAIN(TestSmallWidgets)
#include "test-small-widgets.moc"
<commit_msg>tests/small-widgets: busywidget_on_off<commit_after>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QPixmap>
#include <QPushButton>
#include <QtTest/QtTest>
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include "busywidget.h"
#include "confirmationdialog.h"
#include "elidedannotatedlabel.h"
#include "filepickerdialog.h"
#include "filepickerwidget.h"

#include "ElidedLabel.h"
#include "TSettings.h"
#include "TWizard.h"
#include "TWizardPage.h"

class TestSmallWidgets : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void elidedLabel();
    void elidedAnnotatedLabel();
    void filepickerwidget();
    void filepickerdialog();
    void confirmationDialog();
    void busywidget();
    void busywidget_on_off();
    void statuslabel();
    void twizard();
};

void TestSmallWidgets::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    // Use a custom message handler to filter out unwanted messages
    IF_NOT_VISUAL { qInstallMessageHandler(offscreenMessageOutput); }
}

void TestSmallWidgets::cleanupTestCase()
{
    TSettings::destroy();
}

void TestSmallWidgets::elidedLabel()
{
    // Initialize variables.
    const QString text("this is a long long long piece of text");
    ElidedLabel * elidedlabel = new ElidedLabel();

    VISUAL_INIT(elidedlabel);

    // Set up ElidedText.
    elidedlabel->setElide(Qt::ElideRight);
    elidedlabel->setText(text);

    // The text should be fully visible if there's enough room.
    elidedlabel->setGeometry(100, 100, 1000, 20);
    QVERIFY(elidedlabel->text() == text);
    QVERIFY(elidedlabel->elideText(text).count() == text.count());
    VISUAL_WAIT;

    // The text should be elided if the widget is too narrow.
    elidedlabel->setGeometry(100, 100, 100, 20);
    QVERIFY(elidedlabel->text() == text);
    QVERIFY(elidedlabel->elideText(text).count() < text.count());
    VISUAL_WAIT;

    delete elidedlabel;
}

void TestSmallWidgets::elidedAnnotatedLabel()
{
    ElidedAnnotatedLabel *el = new ElidedAnnotatedLabel();

    const QString plain("grey black long piece of text again grey");
    const QString full("grey black long piece of "
                       "text again grey");
    QVector<QString> texts(3);
    texts[0] = "grey";
    texts[1] = " black long piece of text ";
    texts[2] = "again grey";
    QVector<QString> annotations(6, "");
    annotations[0] = "";
    annotations[1] = "";
    annotations[4] = "";
    annotations[5] = "";

    VISUAL_INIT(el);

    // Set up ElidedText.
    el->setElide(Qt::ElideRight);
    el->setAnnotatedText(texts, annotations);

    // The text should be fully visible if there's enough room.
    el->setGeometry(100, 100, 1000, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() == full.count());
    VISUAL_WAIT;

    // The text should be elided if the widget is too narrow.
    el->setGeometry(100, 100, 100, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() < full.count());
    VISUAL_WAIT;

    delete el;
}

void TestSmallWidgets::filepickerwidget()
{
    FilePickerWidget *fpw = new FilePickerWidget();
    delete fpw;
}

void TestSmallWidgets::filepickerdialog()
{
    QWidget *         widget = new QWidget();
    FilePickerDialog *fpd    = new FilePickerDialog(widget);

    QList<QUrl> myurls({QUrl("file:///tmp")});
    fpd->setSelectedUrls(myurls);
    QVERIFY(fpd->getSelectedUrls() == myurls);

    delete fpd;
    delete widget;
}

void TestSmallWidgets::confirmationDialog()
{
    ConfirmationDialog *confirm = new ConfirmationDialog();
    delete confirm;
}

void TestSmallWidgets::busywidget()
{
    BusyWidget *bw = new BusyWidget();

    VISUAL_INIT(bw);
    IF_NOT_VISUAL { bw->show(); }

    delete bw;
}

void TestSmallWidgets::busywidget_on_off()
{
    BusyWidget *bw = new BusyWidget();

    VISUAL_INIT(bw);
    IF_NOT_VISUAL { bw->show(); }

    // Before starting
    VISUAL_WAIT;

    // Animation
    bw->animate(true);
    QTest::qWait(100);
    VISUAL_WAIT;

    // After animation
    bw->animate(false);
    QTest::qWait(100);
    VISUAL_WAIT;

    delete bw;
}

void TestSmallWidgets::statuslabel()
{
    ElidedLabel *el = new ElidedLabel();
    el->setMinimumWidth(200);

    VISUAL_INIT(el);

    el->messageNormal("normal message");
    VISUAL_WAIT;

    el->messageError("error message");
    VISUAL_WAIT;

    delete el;
}

void TestSmallWidgets::twizard()
{
    TWizard *wizard = new TWizard();

    // Add logo
    QPixmap pix(32, 32);
    pix.fill(Qt::blue);
    wizard->setLogo(pix);

    // Create pages with titles
    TWizardPage *p1 = new TWizardPage();
    TWizardPage *p2 = new TWizardPage();
    p1->setTitle("page 1");
    p2->setTitle("page 2");

    // Add a "proceed" button to each page
    QPushButton *pb1 = new QPushButton(p1);
    pb1->setText("Next");
    pb1->setObjectName("nextButton");
    QPushButton *pb2 = new QPushButton(p2);
    pb2->setText("Finish");
    pb2->setObjectName("finishButton");

    // Add pages to the wizard; must be after the buttons have been added
    wizard->addPages(QList<TWizardPage *>() << p1 << p2);

    // Navigate through the pages.
    VISUAL_INIT(wizard);
    IF_NOT_VISUAL { wizard->open(); }

    wizard->currentPage()->button(TWizardPage::NextButton)->click();
    VISUAL_WAIT;
    wizard->currentPage()->button(TWizardPage::FinishButton)->click();
    VISUAL_WAIT;

    // We should have quit the wizard
    QVERIFY(wizard->isVisible() == false);

    delete wizard;
}

QTEST_MAIN(TestSmallWidgets)
#include "test-small-widgets.moc"
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/jit/xla_device_context.h"

#include <memory>

#include "tensorflow/compiler/jit/xla_device.h"
#include "tensorflow/compiler/jit/xla_launch_util.h"
#include "tensorflow/compiler/tf2xla/literal_util.h"
#include "tensorflow/compiler/tf2xla/shape_util.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/dma_helper.h"
#include "tensorflow/core/platform/mem.h"

namespace tensorflow {

// The allocator used for Tensors assigned to the XLA device.
XlaDeviceAllocator::XlaDeviceAllocator() {}
XlaDeviceAllocator::~XlaDeviceAllocator() = default;

string XlaDeviceAllocator::Name() { return "xla"; }

void* XlaDeviceAllocator::AllocateRaw(size_t alignment, size_t num_bytes) {
  // We always return an empty XlaTensor object, encoded as an opaque tagged
  // pointer. We can return an empty object and ignore num_bytes here because we
  // have control over all of the uses of this device tensor, and can lazily
  // allocate memory when used. This allows us to also know the shape of the
  // allocated Tensor, which is useful if the device's tensor representation
  // differs from the host.
  return XlaTensor::ToOpaquePointer(new XlaTensor());
}

void XlaDeviceAllocator::DeallocateRaw(void* ptr) {
  delete XlaTensor::FromOpaquePointer(ptr);
}

void XlaDeviceAllocator::GetStats(AllocatorStats* stats) { stats->Clear(); }

XlaDeviceContext::XlaDeviceContext(
    std::shared_ptr<se::Stream> compute_stream,
    std::shared_ptr<se::Stream> host_to_device_stream,
    std::shared_ptr<se::Stream> device_to_host_stream, xla::LocalClient* client,
    bool transfer_as_literal,
    XlaCompiler::ShapeRepresentationFn shape_representation_fn,
    thread::ThreadPool* thread_pool)
    : stream_(std::move(compute_stream)),
      host_to_device_stream_(std::move(host_to_device_stream)),
      device_to_host_stream_(std::move(device_to_host_stream)),
      client_(client),
      transfer_manager_(client->backend().transfer_manager()),
      transfer_as_literal_(transfer_as_literal),
      shape_representation_fn_(std::move(shape_representation_fn)),
      thread_pool_(thread_pool) {
  CHECK(host_to_device_stream_ != nullptr);
  CHECK(device_to_host_stream_ != nullptr);
  CHECK(stream_ != nullptr);
  if (!shape_representation_fn_) {
    shape_representation_fn_ =
        [](const TensorShape& shape,
           DataType dtype) -> xla::StatusOr<TensorShape> { return shape; };
  }
}

Status XlaDeviceContext::TransferLiteralToDevice(const Tensor& host_tensor,
                                                 Tensor* device_tensor) const {
  xla::Shape xla_shape;
  TF_RETURN_IF_ERROR(TensorShapeToXLAShape(host_tensor.dtype(),
                                           host_tensor.shape(), &xla_shape));
  // Create a reference to hold onto host_tensor until after the literal has
  // been transferred. Also make sure the literal exists until the function
  // asynchronously completes, as it will be wrapped in an xla::LiteralSlice.
  TensorReference ref(host_tensor);
  auto literal = std::make_shared<xla::BorrowingLiteral>(
      static_cast<const char*>(DMAHelper::base(&host_tensor)), xla_shape);

  XlaTensor* xla_tensor = XlaTensor::FromTensor(device_tensor);
  const xla::ShapedBuffer& shaped_buffer = xla_tensor->shaped_buffer();
  VLOG(1) << "Transfer to device as literal: " << literal->ToString() << " "
          << shaped_buffer.ToString();
  if (UseMultipleStreams() && !transfer_manager_->CanShapedBufferBeAccessedNow(
                                  stream_->parent(), shaped_buffer)) {
    // Initially wait for the compute stream so that memory allocations are
    // synchronized.
    host_to_device_stream_->ThenWaitFor(stream_.get());
  }
  TF_RETURN_IF_ERROR(transfer_manager_->TransferLiteralToDeviceAsync(
      host_to_device_stream_.get(), *literal, shaped_buffer));
  if (UseMultipleStreams()) {
    auto event = std::make_shared<se::Event>(stream_->parent());
    TF_RET_CHECK(event->Init()) << "Event failed to initialize!";
    host_to_device_stream_->ThenRecordEvent(event.get());
    xla_tensor->ResetDefinitionEvent(std::move(event),
                                     host_to_device_stream_.get());
  }
  // Unref the host tensor, and capture the literal shared_ptr too so it goes
  // out of scope when the lambda completes.
  host_to_device_stream_->ThenDoHostCallback([ref, literal]() { ref.Unref(); });

  return Status::OK();
}

void XlaDeviceContext::TransferLiteralFromDevice(
    Tensor* host_tensor, const Tensor& device_tensor,
    const StatusCallback& done) const {
  xla::MutableBorrowingLiteral literal;
  TF_CHECK_OK(HostTensorToMutableBorrowingLiteral(host_tensor, &literal));

  const xla::ShapedBuffer& shaped_buffer =
      XlaTensor::FromTensor(&device_tensor)->shaped_buffer();

  TensorReference ref(device_tensor);
  transfer_manager_->TransferLiteralFromDevice(
      device_to_host_stream_.get(), shaped_buffer, literal,
      [=, &shaped_buffer](xla::Status status) {
        ref.Unref();
        done([&]() -> Status {
          VLOG(1) << "Transfer from device as literal: "
                  << shaped_buffer.ToString();
          return status;
        }());
      });
}

void XlaDeviceContext::CopyCPUTensorToDevice(const Tensor* cpu_tensor,
                                             Device* device,
                                             Tensor* device_tensor,
                                             StatusCallback done) const {
  if (cpu_tensor->NumElements() == 0) {
    VLOG(2) << "CopyCPUTensorToDevice empty tensor";
    done(Status::OK());
    return;
  }

  VLOG(2) << "CopyCPUTensorToDevice "
          << reinterpret_cast<const void*>(cpu_tensor->tensor_data().data())
          << " "
          << reinterpret_cast<const void*>(device_tensor->tensor_data().data())
          << " " << cpu_tensor->NumElements() << " "
          << cpu_tensor->shape().DebugString() << " "
          << device_tensor->shape().DebugString();

  void* src_ptr = const_cast<void*>(DMAHelper::base(cpu_tensor));
  const int64 total_bytes = cpu_tensor->TotalBytes();

  XlaTensor* xla_tensor = XlaTensor::FromTensor(device_tensor);
  CHECK(xla_tensor);

  xla::StatusOr<TensorShape> shape_or_status =
      shape_representation_fn_(device_tensor->shape(), device_tensor->dtype());
  if (!shape_or_status.ok()) {
    done(shape_or_status.status());
    return;
  }
  TensorShape shape = shape_or_status.ValueOrDie();
  if (!xla_tensor->has_shaped_buffer()) {
    Status s =
        xla_tensor->AllocateShapedBuffer(device_tensor->dtype(), shape, client_,
                                         stream_->parent()->device_ordinal());
    if (!s.ok()) {
      done(s);
      return;
    }
  }

  Status status;
  if (transfer_as_literal_) {
    Tensor reshaped_cpu_tensor;
    if (!reshaped_cpu_tensor.CopyFrom(*cpu_tensor, shape)) {
      done(errors::Internal(
          "Tensor::CopyFrom failed when copying from CPU to XLA device"));
      return;
    }
    status = TransferLiteralToDevice(reshaped_cpu_tensor, device_tensor);
  } else {
    se::DeviceMemoryBase dev_dst_ptr =
        XlaTensor::DeviceMemoryFromTensor(*device_tensor);
    host_to_device_stream_->ThenMemcpy(&dev_dst_ptr, src_ptr, total_bytes);
    // TODO(hpucha): Make this asynchronous.
    Status block_status = host_to_device_stream_->BlockHostUntilDone();
    if (!block_status.ok()) {
      status = xla::InternalError(
          "Failed to complete data transfer on stream %p: %s",
          host_to_device_stream_.get(), block_status.error_message().c_str());
    }
  }
  if (status.ok()) {
    xla_tensor->set_host_tensor(*cpu_tensor);
  }
  done(status);
}

void XlaDeviceContext::CopyDeviceTensorToCPU(const Tensor* device_tensor,
                                             absl::string_view tensor_name,
                                             Device* device, Tensor* cpu_tensor,
                                             StatusCallback done) {
  if (device_tensor->NumElements() == 0) {
    VLOG(2) << "CopyDeviceTensorToCPU empty tensor";
    done(Status::OK());
    return;
  }
  VLOG(2) << "CopyDeviceTensorToCPU "
          << reinterpret_cast<const void*>(device_tensor->tensor_data().data())
          << " "
          << reinterpret_cast<const void*>(cpu_tensor->tensor_data().data())
          << " " << device_tensor->NumElements() << " "
          << cpu_tensor->shape().DebugString() << " "
          << device_tensor->shape().DebugString();

  const int64 total_bytes = cpu_tensor->TotalBytes();
  se::DeviceMemoryBase dev_src_ptr =
      XlaTensor::DeviceMemoryFromTensor(*device_tensor);
  void* dst_ptr = DMAHelper::base(cpu_tensor);
  XlaTensor* xla_tensor = XlaTensor::FromTensor(device_tensor);

  xla_tensor->WaitForDefinitionEventOnStream(device_to_host_stream_.get());

  Status status;
  if (transfer_as_literal_) {
    TransferLiteralFromDevice(cpu_tensor, *device_tensor, done);
    return;
  } else {
    device_to_host_stream_->ThenMemcpy(dst_ptr, dev_src_ptr, total_bytes);
    // TODO(hpucha): Make this asynchronous.
    Status block_status = device_to_host_stream_->BlockHostUntilDone();
    if (!block_status.ok()) {
      status = xla::InternalError(
          "Failed to complete data transfer on stream %p: %s", stream_.get(),
          block_status.error_message().c_str());
    }
  }

  done(status);
}

}  // namespace tensorflow
<commit_msg>[TF:XLA] Clarify comment on XlaDeviceContext::TransferLiteralToDevice.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/jit/xla_device_context.h"

#include <memory>

#include "tensorflow/compiler/jit/xla_device.h"
#include "tensorflow/compiler/jit/xla_launch_util.h"
#include "tensorflow/compiler/tf2xla/literal_util.h"
#include "tensorflow/compiler/tf2xla/shape_util.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/dma_helper.h"
#include "tensorflow/core/platform/mem.h"

namespace tensorflow {

// The allocator used for Tensors assigned to the XLA device.
XlaDeviceAllocator::XlaDeviceAllocator() {}
XlaDeviceAllocator::~XlaDeviceAllocator() = default;

string XlaDeviceAllocator::Name() { return "xla"; }

void* XlaDeviceAllocator::AllocateRaw(size_t alignment, size_t num_bytes) {
  // We always return an empty XlaTensor object, encoded as an opaque tagged
  // pointer. We can return an empty object and ignore num_bytes here because we
  // have control over all of the uses of this device tensor, and can lazily
  // allocate memory when used. This allows us to also know the shape of the
  // allocated Tensor, which is useful if the device's tensor representation
  // differs from the host.
  return XlaTensor::ToOpaquePointer(new XlaTensor());
}

void XlaDeviceAllocator::DeallocateRaw(void* ptr) {
  delete XlaTensor::FromOpaquePointer(ptr);
}

void XlaDeviceAllocator::GetStats(AllocatorStats* stats) { stats->Clear(); }

XlaDeviceContext::XlaDeviceContext(
    std::shared_ptr<se::Stream> compute_stream,
    std::shared_ptr<se::Stream> host_to_device_stream,
    std::shared_ptr<se::Stream> device_to_host_stream, xla::LocalClient* client,
    bool transfer_as_literal,
    XlaCompiler::ShapeRepresentationFn shape_representation_fn,
    thread::ThreadPool* thread_pool)
    : stream_(std::move(compute_stream)),
      host_to_device_stream_(std::move(host_to_device_stream)),
      device_to_host_stream_(std::move(device_to_host_stream)),
      client_(client),
      transfer_manager_(client->backend().transfer_manager()),
      transfer_as_literal_(transfer_as_literal),
      shape_representation_fn_(std::move(shape_representation_fn)),
      thread_pool_(thread_pool) {
  CHECK(host_to_device_stream_ != nullptr);
  CHECK(device_to_host_stream_ != nullptr);
  CHECK(stream_ != nullptr);
  if (!shape_representation_fn_) {
    shape_representation_fn_ =
        [](const TensorShape& shape,
           DataType dtype) -> xla::StatusOr<TensorShape> { return shape; };
  }
}

Status XlaDeviceContext::TransferLiteralToDevice(const Tensor& host_tensor,
                                                 Tensor* device_tensor) const {
  xla::Shape xla_shape;
  TF_RETURN_IF_ERROR(TensorShapeToXLAShape(host_tensor.dtype(),
                                           host_tensor.shape(), &xla_shape));
  // Create a reference to hold onto host_tensor until after the literal has
  // been transferred. Also make sure the literal exists until the function
  // asynchronously completes, as it will be wrapped in an xla::LiteralSlice.
  TensorReference ref(host_tensor);
  auto literal = std::make_shared<xla::BorrowingLiteral>(
      static_cast<const char*>(DMAHelper::base(&host_tensor)), xla_shape);

  XlaTensor* xla_tensor = XlaTensor::FromTensor(device_tensor);
  const xla::ShapedBuffer& shaped_buffer = xla_tensor->shaped_buffer();
  VLOG(1) << "Transfer to device as literal: " << literal->ToString() << " "
          << shaped_buffer.ToString();
  if (UseMultipleStreams() && !transfer_manager_->CanShapedBufferBeAccessedNow(
                                  stream_->parent(), shaped_buffer)) {
    // Initially wait for the compute stream so that memory allocations are
    // synchronized.
    host_to_device_stream_->ThenWaitFor(stream_.get());
  }
  TF_RETURN_IF_ERROR(transfer_manager_->TransferLiteralToDeviceAsync(
      host_to_device_stream_.get(), *literal, shaped_buffer));
  if (UseMultipleStreams()) {
    auto event = std::make_shared<se::Event>(stream_->parent());
    TF_RET_CHECK(event->Init()) << "Event failed to initialize!";
    host_to_device_stream_->ThenRecordEvent(event.get());
    xla_tensor->ResetDefinitionEvent(std::move(event),
                                     host_to_device_stream_.get());
  }
  // Unref the host tensor, and capture the literal shared_ptr too so it goes
  // out of scope when the lambda completes.
  // We don't defer the call to done() onto the stream here, and the reasons why
  // this is correct are subtle. We assume that:
  // a) all consumers of the device tensor will wait for its definition event.
  // b) if the tensor is destroyed, then the memory allocator will not hand out
  //    the same buffers until the transfer has completed.
  host_to_device_stream_->ThenDoHostCallback([ref, literal]() { ref.Unref(); });

  return Status::OK();
}

void XlaDeviceContext::TransferLiteralFromDevice(
    Tensor* host_tensor, const Tensor& device_tensor,
    const StatusCallback& done) const {
  xla::MutableBorrowingLiteral literal;
  TF_CHECK_OK(HostTensorToMutableBorrowingLiteral(host_tensor, &literal));

  const xla::ShapedBuffer& shaped_buffer =
      XlaTensor::FromTensor(&device_tensor)->shaped_buffer();

  TensorReference ref(device_tensor);
  transfer_manager_->TransferLiteralFromDevice(
      device_to_host_stream_.get(), shaped_buffer, literal,
      [=, &shaped_buffer](xla::Status status) {
        ref.Unref();
        done([&]() -> Status {
          VLOG(1) << "Transfer from device as literal: "
                  << shaped_buffer.ToString();
          return status;
        }());
      });
}

void XlaDeviceContext::CopyCPUTensorToDevice(const Tensor* cpu_tensor,
                                             Device* device,
                                             Tensor* device_tensor,
                                             StatusCallback done) const {
  if (cpu_tensor->NumElements() == 0) {
    VLOG(2) << "CopyCPUTensorToDevice empty tensor";
    done(Status::OK());
    return;
  }

  VLOG(2) << "CopyCPUTensorToDevice "
          << reinterpret_cast<const void*>(cpu_tensor->tensor_data().data())
          << " "
          << reinterpret_cast<const void*>(device_tensor->tensor_data().data())
          << " " << cpu_tensor->NumElements() << " "
          << cpu_tensor->shape().DebugString() << " "
          << device_tensor->shape().DebugString();

  void* src_ptr = const_cast<void*>(DMAHelper::base(cpu_tensor));
  const int64 total_bytes = cpu_tensor->TotalBytes();

  XlaTensor* xla_tensor = XlaTensor::FromTensor(device_tensor);
  CHECK(xla_tensor);

  xla::StatusOr<TensorShape> shape_or_status =
      shape_representation_fn_(device_tensor->shape(), device_tensor->dtype());
  if (!shape_or_status.ok()) {
    done(shape_or_status.status());
    return;
  }
  TensorShape shape = shape_or_status.ValueOrDie();
  if (!xla_tensor->has_shaped_buffer()) {
    Status s =
        xla_tensor->AllocateShapedBuffer(device_tensor->dtype(), shape, client_,
                                         stream_->parent()->device_ordinal());
    if (!s.ok()) {
      done(s);
      return;
    }
  }

  Status status;
  if (transfer_as_literal_) {
    Tensor reshaped_cpu_tensor;
    if (!reshaped_cpu_tensor.CopyFrom(*cpu_tensor, shape)) {
      done(errors::Internal(
          "Tensor::CopyFrom failed when copying from CPU to XLA device"));
      return;
    }
    status = TransferLiteralToDevice(reshaped_cpu_tensor, device_tensor);
  } else {
    se::DeviceMemoryBase dev_dst_ptr =
        XlaTensor::DeviceMemoryFromTensor(*device_tensor);
    host_to_device_stream_->ThenMemcpy(&dev_dst_ptr, src_ptr, total_bytes);
    // TODO(hpucha): Make this asynchronous.
    Status block_status = host_to_device_stream_->BlockHostUntilDone();
    if (!block_status.ok()) {
      status = xla::InternalError(
          "Failed to complete data transfer on stream %p: %s",
          host_to_device_stream_.get(), block_status.error_message().c_str());
    }
  }
  if (status.ok()) {
    xla_tensor->set_host_tensor(*cpu_tensor);
  }
  done(status);
}

void XlaDeviceContext::CopyDeviceTensorToCPU(const Tensor* device_tensor,
                                             absl::string_view tensor_name,
                                             Device* device, Tensor* cpu_tensor,
                                             StatusCallback done) {
  if (device_tensor->NumElements() == 0) {
    VLOG(2) << "CopyDeviceTensorToCPU empty tensor";
    done(Status::OK());
    return;
  }
  VLOG(2) << "CopyDeviceTensorToCPU "
          << reinterpret_cast<const void*>(device_tensor->tensor_data().data())
          << " "
          << reinterpret_cast<const void*>(cpu_tensor->tensor_data().data())
          << " " << device_tensor->NumElements() << " "
          << cpu_tensor->shape().DebugString() << " "
          << device_tensor->shape().DebugString();

  const int64 total_bytes = cpu_tensor->TotalBytes();
  se::DeviceMemoryBase dev_src_ptr =
      XlaTensor::DeviceMemoryFromTensor(*device_tensor);
  void* dst_ptr = DMAHelper::base(cpu_tensor);
  XlaTensor* xla_tensor = XlaTensor::FromTensor(device_tensor);

  xla_tensor->WaitForDefinitionEventOnStream(device_to_host_stream_.get());

  Status status;
  if (transfer_as_literal_) {
    TransferLiteralFromDevice(cpu_tensor, *device_tensor, done);
    return;
  } else {
    device_to_host_stream_->ThenMemcpy(dst_ptr, dev_src_ptr, total_bytes);
    // TODO(hpucha): Make this asynchronous.
    Status block_status = device_to_host_stream_->BlockHostUntilDone();
    if (!block_status.ok()) {
      status = xla::InternalError(
          "Failed to complete data transfer on stream %p: %s", stream_.get(),
          block_status.error_message().c_str());
    }
  }

  done(status);
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>#pragma once
/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#ifndef _QI_ATOMIC_HPP_
#define _QI_ATOMIC_HPP_

#ifdef _MSC_VER
# include <windows.h>

extern "C" long __cdecl _InterlockedIncrement(long volatile *);
extern "C" long __cdecl _InterlockedDecrement(long volatile *);

# pragma intrinsic(_InterlockedIncrement)
# pragma intrinsic(_InterlockedDecrement)

#endif

#include <boost/static_assert.hpp>

#include <qi/config.hpp>
#include <qi/macro.hpp>

namespace qi
{
  inline long testAndSet(long* cond)
  {
#ifdef __GNUC__
    return __sync_bool_compare_and_swap(cond, 0, 1);
#endif
#ifdef _MSC_VER
    return 1 - InterlockedCompareExchange(cond, 1, 0);
#endif
  }

  /* /!\ WARNING
  * The volatile is needed, because there is no memory barrier
  * surrounding the simple getter operator.
  * AtomicBase has public member so that it can be initialized at
  * static-initialization time.
  */
  template <typename T>
  struct AtomicBase
  {
  public:

    /* prefix operators */
    inline T operator++();
    inline T operator--();
    inline AtomicBase<T>& operator=(T value);
    inline T swap(T value);

    inline T operator*()
    {
      return _value;
    }

  public:
    BOOST_STATIC_ASSERT_MSG(sizeof(T) == sizeof(int), "qi::Atomic is only supprted for int-like types");

    volatile T _value;
  };

  template <typename T>
  class Atomic: public AtomicBase<T>
  {
  public:
    Atomic()
    {
      this->_value = 0;
    }

    Atomic(T value)
    {
      this->_value = value;
    }
  };
#ifdef __GNUC__
    template <typename T>
    inline T AtomicBase<T>::operator++()
    {
      return __sync_add_and_fetch(&_value, 1);
    }

    template <typename T>
    inline T AtomicBase<T>::operator--()
    {
      return __sync_sub_and_fetch(&_value, 1);
    }

    template <typename T>
    inline AtomicBase<T>& AtomicBase<T>::operator=(T value)
    {
      __sync_lock_test_and_set(&_value, value);
      return *this;
    }

    template <typename T>
    inline T AtomicBase<T>::swap(T value)
    {
      return __sync_lock_test_and_set(&_value, value);
    }
#endif

#ifdef _MSC_VER

  template <>
  inline int AtomicBase<int>::operator++()
  {
    return _InterlockedIncrement(reinterpret_cast<long*>(&_value));
  }

  template <>
  inline int AtomicBase<int>::operator--()
  {
    return _InterlockedDecrement(reinterpret_cast<long*>(&_value));
  }

  template<>
  inline AtomicBase<int>& AtomicBase<int>::operator=(int value)
  {
    InterlockedExchange(reinterpret_cast<long*>(&_value), value);
    return *this;
  }

  template<>
  inline int AtomicBase<int>::swap(int value)
  {
    return InterlockedExchange(reinterpret_cast<long*>(&_value), value);
  }

  template <>
  inline unsigned int AtomicBase<unsigned int>::operator++()
  {
    return _InterlockedIncrement(reinterpret_cast<long*>(&_value));
  }

  template <>
  inline unsigned int AtomicBase<unsigned int>::operator--()
  {
    return _InterlockedDecrement(reinterpret_cast<long*>(&_value));
  }

  template<>
  inline AtomicBase<unsigned int>& AtomicBase<unsigned int>::operator=(unsigned int value)
  {
    InterlockedExchange(reinterpret_cast<long*>(&_value), value);
    return *this;
  }

  template<>
  inline unsigned int AtomicBase<unsigned int>::swap(unsigned int value)
  {
    return InterlockedExchange(reinterpret_cast<long*>(&_value), value);
  }

#endif

}

#endif  // _QI_ATOMIC_HPP_
<commit_msg>Atomic: Fix for 64bit WIN32<commit_after>#pragma once
/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#ifndef _QI_ATOMIC_HPP_
#define _QI_ATOMIC_HPP_

#ifdef _MSC_VER
# include <windows.h>

extern "C" long __cdecl _InterlockedIncrement(long volatile *);
extern "C" long __cdecl _InterlockedDecrement(long volatile *);

# pragma intrinsic(_InterlockedIncrement)
# pragma intrinsic(_InterlockedDecrement)

#endif

#include <boost/static_assert.hpp>

#include <qi/config.hpp>
#include <qi/macro.hpp>

namespace qi
{
  inline long testAndSet(long* cond)
  {
#ifdef __GNUC__
    return __sync_bool_compare_and_swap(cond, 0, 1);
#endif
#ifdef _MSC_VER
    return 1 - InterlockedCompareExchange(cond, 1, 0);
#endif
  }

  /* /!\ WARNING
  * The volatile is needed, because there is no memory barrier
  * surrounding the simple getter operator.
  * AtomicBase has public member so that it can be initialized at
  * static-initialization time.
  */
  template <typename T>
  struct AtomicBase
  {
  public:

    /* prefix operators */
    inline T operator++();
    inline T operator--();
    inline AtomicBase<T>& operator=(T value);
    inline T swap(T value);

    inline T operator*()
    {
      return _value;
    }

  public:
    BOOST_STATIC_ASSERT_MSG(sizeof(T) == sizeof(int), "qi::Atomic is only supprted for int-like types");

    volatile
#ifdef _MSC_VER
    long
#else
    T
#endif
       _value;
  };

  template <typename T>
  class Atomic: public AtomicBase<T>
  {
  public:
    Atomic()
    {
      this->_value = 0;
    }

    Atomic(T value)
    {
      this->_value = value;
    }
  };
#ifdef __GNUC__
    template <typename T>
    inline T AtomicBase<T>::operator++()
    {
      return __sync_add_and_fetch(&_value, 1);
    }

    template <typename T>
    inline T AtomicBase<T>::operator--()
    {
      return __sync_sub_and_fetch(&_value, 1);
    }

    template <typename T>
    inline AtomicBase<T>& AtomicBase<T>::operator=(T value)
    {
      __sync_lock_test_and_set(&_value, value);
      return *this;
    }

    template <typename T>
    inline T AtomicBase<T>::swap(T value)
    {
      return __sync_lock_test_and_set(&_value, value);
    }
#endif

#ifdef _MSC_VER

  template <>
  inline int AtomicBase<int>::operator++()
  {
    return _InterlockedIncrement(&_value);
  }

  template <>
  inline int AtomicBase<int>::operator--()
  {
    return _InterlockedDecrement(&_value);
  }

  template<>
  inline AtomicBase<int>& AtomicBase<int>::operator=(int value)
  {
    InterlockedExchange(&_value, value);
    return *this;
  }

  template<>
  inline int AtomicBase<int>::swap(int value)
  {
    return InterlockedExchange(&_value, value);
  }

  template <>
  inline unsigned int AtomicBase<unsigned int>::operator++()
  {
    return _InterlockedIncrement(&_value);
  }

  template <>
  inline unsigned int AtomicBase<unsigned int>::operator--()
  {
    return _InterlockedDecrement(&_value);
  }

  template<>
  inline AtomicBase<unsigned int>& AtomicBase<unsigned int>::operator=(unsigned int value)
  {
    InterlockedExchange(&_value, value);
    return *this;
  }

  template<>
  inline unsigned int AtomicBase<unsigned int>::swap(unsigned int value)
  {
    return InterlockedExchange(&_value, value);
  }

#endif

}

#endif  // _QI_ATOMIC_HPP_
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "butler.hpp"

using namespace butler;
using namespace std::string_literals;

Butler::Butler(SharedDisk disk, std::string root, Options opt)
  : disk_(disk), root_(root), options_(opt)
{}

void Butler::process(mana::Request_ptr req, mana::Response_ptr res, mana::Next next)
{
  // if not a valid request
  if(req->method() != http::GET && req->method() != http::HEAD) {
    if(options_.fallthrough) {
      return (*next)();
    }
    res->add_header(http::header_fields::Entity::Allow, "GET, HEAD"s);
    res->send_code(http::Method_Not_Allowed);
    return;
  }

  // get path
  std::string path = req->uri().path();
  // resolve extension
  auto ext = get_extension(path);
  // concatenate root with path, example: / => /public/
  path = root_ + path;

  // no extension found
  if(ext.empty() and !options_.index.empty()) {
    if(path.back() != '/') path += '/';
    // lets try to see if we can serve an index
    path += options_.index[0]; // only check first one for now, else we have to use fs().ls
    disk_->fs().cstat(path,
    [this, req, res, next, path](auto err, const auto& entry)
    {
      //printf("<Butler> err=%s path=%s entry=%s\n",
      //  err.to_string().c_str(), path.c_str(), entry.name().c_str());
      // no index was found on this path, go to next middleware
      if(err or !entry.is_file()) {
        return (*next)();
      }
      // we got an index, lets send it
      else {
        http::Mime_Type mime = http::extension_to_type(get_extension(path));
        res->add_header(http::header_fields::Entity::Content_Type, mime);
        return res->send_file({disk_, entry});
      }
    });
  }
  // we found an extension, this is a (probably) a file request
  else {
    //printf("<Butler> Extension found - assuming request for file.\n");
    disk_->fs().cstat(path,
    [this, req, res, next, path](auto err, const auto& entry)
    {
      //printf("<Butler> err=%s path=%s entry=%s\n",
      //  err.to_string().c_str(), path.c_str(), entry.name().c_str());
      if(err or !entry.is_file()) {
        #ifdef VERBOSE_WEBSERVER
        printf("<Butler> File not found. Replying with 404.\n");
        #endif
        res->send_code(http::Not_Found);
        return;
        /*
        if(!options_.fallthrough) {
          printf("<Butler> File not found. Replying with 404.\n");
          return res->send_code(http::Not_Found);
        }
        else {
          return (*next)();
        }*/
      }
      else {
        #ifdef VERBOSE_WEBSERVER
        printf("<Butler> Found file: %s (%llu B)\n", entry.name().c_str(), entry.size());
        #endif
        http::Mime_Type mime = http::extension_to_type(get_extension(path));
        res->add_header(http::header_fields::Entity::Content_Type, mime);
        res->send_file({disk_, entry});
        return;
      }
    });
  }
}

std::string Butler::get_extension(const std::string& path) const {
  std::string ext;
  auto idx = path.find_last_of(".");
  // Find extension
  if(idx != std::string::npos) {
    ext = path.substr(idx+1);
  }
  return ext;
}
<commit_msg>Added include for http to know about MIME type<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "butler.hpp"
#include <mana/http> // http::Mime_Type

using namespace butler;
using namespace std::string_literals;

Butler::Butler(SharedDisk disk, std::string root, Options opt)
  : disk_(disk), root_(root), options_(opt)
{}

void Butler::process(mana::Request_ptr req, mana::Response_ptr res, mana::Next next)
{
  // if not a valid request
  if(req->method() != http::GET && req->method() != http::HEAD) {
    if(options_.fallthrough) {
      return (*next)();
    }
    res->add_header(http::header_fields::Entity::Allow, "GET, HEAD"s);
    res->send_code(http::Method_Not_Allowed);
    return;
  }

  // get path
  std::string path = req->uri().path();
  // resolve extension
  auto ext = get_extension(path);
  // concatenate root with path, example: / => /public/
  path = root_ + path;

  // no extension found
  if(ext.empty() and !options_.index.empty()) {
    if(path.back() != '/') path += '/';
    // lets try to see if we can serve an index
    path += options_.index[0]; // only check first one for now, else we have to use fs().ls
    disk_->fs().cstat(path,
    [this, req, res, next, path](auto err, const auto& entry)
    {
      //printf("<Butler> err=%s path=%s entry=%s\n",
      //  err.to_string().c_str(), path.c_str(), entry.name().c_str());
      // no index was found on this path, go to next middleware
      if(err or !entry.is_file()) {
        return (*next)();
      }
      // we got an index, lets send it
      else {
        http::Mime_Type mime = http::extension_to_type(get_extension(path));
        res->add_header(http::header_fields::Entity::Content_Type, mime);
        return res->send_file({disk_, entry});
      }
    });
  }
  // we found an extension, this is a (probably) a file request
  else {
    //printf("<Butler> Extension found - assuming request for file.\n");
    disk_->fs().cstat(path,
    [this, req, res, next, path](auto err, const auto& entry)
    {
      //printf("<Butler> err=%s path=%s entry=%s\n",
      //  err.to_string().c_str(), path.c_str(), entry.name().c_str());
      if(err or !entry.is_file()) {
        #ifdef VERBOSE_WEBSERVER
        printf("<Butler> File not found. Replying with 404.\n");
        #endif
        res->send_code(http::Not_Found);
        return;
        /*
        if(!options_.fallthrough) {
          printf("<Butler> File not found. Replying with 404.\n");
          return res->send_code(http::Not_Found);
        }
        else {
          return (*next)();
        }*/
      }
      else {
        #ifdef VERBOSE_WEBSERVER
        printf("<Butler> Found file: %s (%llu B)\n", entry.name().c_str(), entry.size());
        #endif
        http::Mime_Type mime = http::extension_to_type(get_extension(path));
        res->add_header(http::header_fields::Entity::Content_Type, mime);
        res->send_file({disk_, entry});
        return;
      }
    });
  }
}

std::string Butler::get_extension(const std::string& path) const {
  std::string ext;
  auto idx = path.find_last_of(".");
  // Find extension
  if(idx != std::string::npos) {
    ext = path.substr(idx+1);
  }
  return ext;
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/kernels/internal/reference/softmax.h"

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/common.h"
#include "tensorflow/lite/kernels/internal/quantization_util.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/ceva/ceva_tflm_lib.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/softmax.h"
#ifdef MCPS_MEASUREMENT
#include "mcps_macros.h"
#endif

#if defined(CEVA_BX1) || defined(CEVA_SP500)
extern int32_t* CEVA_TFLM_KERNELS_SCRATCH;
extern int32_t CEVA_TFLM_KERNELS_SCRATCH_SIZE_VAL;
#endif

namespace tflite {
namespace {

// Takes a tensor and performs softmax along the last dimension.
void SoftmaxFloatCEVA(const TfLiteEvalTensor* input, TfLiteEvalTensor* output,
                      const SoftmaxParams& op_data) {
  const RuntimeShape& input_shape = tflite::micro::GetTensorShape(input);
  const float* input_data = tflite::micro::GetTensorData<float>(input);
  const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output);
  float* output_data = tflite::micro::GetTensorData<float>(output);

  const float beta = static_cast<float>(op_data.beta);
  const int trailing_dim = input_shape.DimensionsCount() - 1;
  const int outer_size =
      MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
  const int depth =
      MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
  int outer_size_mcps = outer_size;
  int depth_mcps = depth;

#ifdef MCPS_MEASUREMENT
  MCPS_START_ONE;
#endif
  for (int i = 0; i < outer_size; ++i) {
    CEVA_TFLM_Softmax_Float32(&input_data[i * depth], &output_data[i * depth],
                              beta, depth);
  }
#ifdef MCPS_MEASUREMENT
  MCPS_STOP_ONE(
      "Test params:Call CEVA_TFLM_Softmax_Float32 %d times, inetrnal loop = %d",
      outer_size_mcps, depth_mcps);
#endif
}

TfLiteStatus SoftmaxQuantizedCEVA(TfLiteContext* context,
                                  const TfLiteEvalTensor* input,
                                  TfLiteEvalTensor* output,
                                  const SoftmaxParams& op_data) {
  if (input->type == kTfLiteUInt8) {
    tflite::reference_ops::Softmax(
        op_data, tflite::micro::GetTensorShape(input),
        tflite::micro::GetTensorData<uint8_t>(input),
        tflite::micro::GetTensorShape(output),
        tflite::micro::GetTensorData<uint8_t>(output));
  } else if (input->type == kTfLiteInt8) {
    if (output->type == kTfLiteInt16) {
      tflite::reference_ops::Softmax(
          op_data, tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int8_t>(input),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int16_t>(output));
    } else {
      const RuntimeShape& input_shape = tflite::micro::GetTensorShape(input);
      const int8_t* input_data = tflite::micro::GetTensorData<int8_t>(input);

      const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output);
      int8_t* output_data = tflite::micro::GetTensorData<int8_t>(output);

      const int32_t input_beta_multiplier =
          static_cast<int32_t>(op_data.input_multiplier);
      const int32_t input_beta_left_shift =
          static_cast<int32_t>(op_data.input_left_shift);
      const int trailing_dim = input_shape.DimensionsCount() - 1;
      const int outer_size =
          MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
      const int depth =
          MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
      int outer_size_mcps = outer_size;
      int depth_mcps = depth;

      if (depth > CEVA_TFLM_KERNELS_SCRATCH_SIZE_VAL) {
        TF_LITE_KERNEL_LOG(context, "Scratch size (%d) less that required (%d)",
                           CEVA_TFLM_KERNELS_SCRATCH_SIZE_VAL, depth);
        return kTfLiteError;
      }

#ifdef MCPS_MEASUREMENT
      MCPS_START_ONE;
#endif
      for (int i = 0; i < outer_size; ++i) {
        CEVA_TFLM_Softmax_Int8(&input_data[i * depth], &output_data[i * depth],
                               input_beta_multiplier, input_beta_left_shift,
                               depth, CEVA_TFLM_KERNELS_SCRATCH);
      }
#ifdef MCPS_MEASUREMENT
      MCPS_STOP_ONE(
          "Test params:Call CEVA_TFLM_Softmax_Int8 %d times, inetrnal loop = "
          "%d",
          outer_size_mcps, depth_mcps);
#endif
    }
  } else {
    tflite::reference_ops::SoftmaxInt16(
        op_data, tflite::micro::GetTensorShape(input),
        tflite::micro::GetTensorData<int16_t>(input),
        tflite::micro::GetTensorShape(output),
        tflite::micro::GetTensorData<int16_t>(output));
  }

  return kTfLiteOk;
}

TfLiteStatus SoftmaxEvalCEVA(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0);
  TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0);

  TFLITE_DCHECK(node->user_data != nullptr);
  SoftmaxParams op_data = *static_cast<SoftmaxParams*>(node->user_data);

  switch (input->type) {
    case kTfLiteFloat32: {
      SoftmaxFloatCEVA(input, output, op_data);
      return kTfLiteOk;
    }
    case kTfLiteInt8:
    case kTfLiteUInt8:
    case kTfLiteInt16: {
      return SoftmaxQuantizedCEVA(context, input, output, op_data);
    }
    default:
      TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
                         TfLiteTypeGetName(input->type), input->type);
      return kTfLiteError;
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
#if defined(CEVA_BX1) || defined(CEVA_SP500)
  return SoftmaxEvalCEVA(context, node);
#else
  return SoftmaxEval(context, node);  // reference fallback
#endif
}
}  // namespace

TfLiteRegistration Register_SOFTMAX() {
  return {/*init=*/SoftmaxInit,
          /*free=*/nullptr,
          /*prepare=*/SoftmaxPrepare,
          /*invoke=*/Eval,
          /*profiling_string=*/nullptr,
          /*builtin_code=*/0,
          /*custom_name=*/nullptr,
          /*version=*/0};
}

}  // namespace tflite
<commit_msg>fixed include path<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/kernels/internal/reference/softmax.h"

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/common.h"
#include "tensorflow/lite/kernels/internal/quantization_util.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/ceva/ceva_tflm_lib.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/softmax.h"
#ifdef MCPS_MEASUREMENT
#include "tensorflow/lite/micro/kernels/ceva/mcps_macros.h"
#endif

#if defined(CEVA_BX1) || defined(CEVA_SP500)
extern int32_t* CEVA_TFLM_KERNELS_SCRATCH;
extern int32_t CEVA_TFLM_KERNELS_SCRATCH_SIZE_VAL;
#endif

namespace tflite {
namespace {

// Takes a tensor and performs softmax along the last dimension.
void SoftmaxFloatCEVA(const TfLiteEvalTensor* input, TfLiteEvalTensor* output,
                      const SoftmaxParams& op_data) {
  const RuntimeShape& input_shape = tflite::micro::GetTensorShape(input);
  const float* input_data = tflite::micro::GetTensorData<float>(input);
  const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output);
  float* output_data = tflite::micro::GetTensorData<float>(output);

  const float beta = static_cast<float>(op_data.beta);
  const int trailing_dim = input_shape.DimensionsCount() - 1;
  const int outer_size =
      MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
  const int depth =
      MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
  int outer_size_mcps = outer_size;
  int depth_mcps = depth;

#ifdef MCPS_MEASUREMENT
  MCPS_START_ONE;
#endif
  for (int i = 0; i < outer_size; ++i) {
    CEVA_TFLM_Softmax_Float32(&input_data[i * depth], &output_data[i * depth],
                              beta, depth);
  }
#ifdef MCPS_MEASUREMENT
  MCPS_STOP_ONE(
      "Test params:Call CEVA_TFLM_Softmax_Float32 %d times, inetrnal loop = %d",
      outer_size_mcps, depth_mcps);
#endif
}

TfLiteStatus SoftmaxQuantizedCEVA(TfLiteContext* context,
                                  const TfLiteEvalTensor* input,
                                  TfLiteEvalTensor* output,
                                  const SoftmaxParams& op_data) {
  if (input->type == kTfLiteUInt8) {
    tflite::reference_ops::Softmax(
        op_data, tflite::micro::GetTensorShape(input),
        tflite::micro::GetTensorData<uint8_t>(input),
        tflite::micro::GetTensorShape(output),
        tflite::micro::GetTensorData<uint8_t>(output));
  } else if (input->type == kTfLiteInt8) {
    if (output->type == kTfLiteInt16) {
      tflite::reference_ops::Softmax(
          op_data, tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int8_t>(input),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int16_t>(output));
    } else {
      const RuntimeShape& input_shape = tflite::micro::GetTensorShape(input);
      const int8_t* input_data = tflite::micro::GetTensorData<int8_t>(input);

      const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output);
      int8_t* output_data = tflite::micro::GetTensorData<int8_t>(output);

      const int32_t input_beta_multiplier =
          static_cast<int32_t>(op_data.input_multiplier);
      const int32_t input_beta_left_shift =
          static_cast<int32_t>(op_data.input_left_shift);
      const int trailing_dim = input_shape.DimensionsCount() - 1;
      const int outer_size =
          MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape);
      const int depth =
          MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
      int outer_size_mcps = outer_size;
      int depth_mcps = depth;

      if (depth > CEVA_TFLM_KERNELS_SCRATCH_SIZE_VAL) {
        TF_LITE_KERNEL_LOG(context, "Scratch size (%d) less that required (%d)",
                           CEVA_TFLM_KERNELS_SCRATCH_SIZE_VAL, depth);
        return kTfLiteError;
      }

#ifdef MCPS_MEASUREMENT
      MCPS_START_ONE;
#endif
      for (int i = 0; i < outer_size; ++i) {
        CEVA_TFLM_Softmax_Int8(&input_data[i * depth], &output_data[i * depth],
                               input_beta_multiplier, input_beta_left_shift,
                               depth, CEVA_TFLM_KERNELS_SCRATCH);
      }
#ifdef MCPS_MEASUREMENT
      MCPS_STOP_ONE(
          "Test params:Call CEVA_TFLM_Softmax_Int8 %d times, inetrnal loop = "
          "%d",
          outer_size_mcps, depth_mcps);
#endif
    }
  } else {
    tflite::reference_ops::SoftmaxInt16(
        op_data, tflite::micro::GetTensorShape(input),
        tflite::micro::GetTensorData<int16_t>(input),
        tflite::micro::GetTensorShape(output),
        tflite::micro::GetTensorData<int16_t>(output));
  }

  return kTfLiteOk;
}

TfLiteStatus SoftmaxEvalCEVA(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0);
  TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0);

  TFLITE_DCHECK(node->user_data != nullptr);
  SoftmaxParams op_data = *static_cast<SoftmaxParams*>(node->user_data);

  switch (input->type) {
    case kTfLiteFloat32: {
      SoftmaxFloatCEVA(input, output, op_data);
      return kTfLiteOk;
    }
    case kTfLiteInt8:
    case kTfLiteUInt8:
    case kTfLiteInt16: {
      return SoftmaxQuantizedCEVA(context, input, output, op_data);
    }
    default:
      TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
                         TfLiteTypeGetName(input->type), input->type);
      return kTfLiteError;
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
#if defined(CEVA_BX1) || defined(CEVA_SP500)
  return SoftmaxEvalCEVA(context, node);
#else
  return SoftmaxEval(context, node);  // reference fallback
#endif
}
}  // namespace

TfLiteRegistration Register_SOFTMAX() {
  return {/*init=*/SoftmaxInit,
          /*free=*/nullptr,
          /*prepare=*/SoftmaxPrepare,
          /*invoke=*/Eval,
          /*profiling_string=*/nullptr,
          /*builtin_code=*/0,
          /*custom_name=*/nullptr,
          /*version=*/0};
}

}  // namespace tflite
<|endoftext|>