<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: filedlg2.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 15:13:20 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _FILEDLG2_HXX
#define _FILEDLG2_HXX

#ifndef _TOOLS_DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif
#ifndef _FSYS_HXX //autogen
#include <tools/fsys.hxx>
#endif
#ifndef _SV_BUTTON_HXX //autogen wg. PushButton
#include <vcl/button.hxx>
#endif
#ifndef _VCL_UNOHELP_HXX
#include <vcl/unohelp.hxx>
#endif

class FixedText;
class Edit;
class ListBox;
class ListBox;
class Button;

class PathDialog;
class FileDialog;
class ImpPathDialog;

struct ImpFilterItem
{
    String aName;
    String aMask;

    ImpFilterItem( const String & rFilter, const String & rMask )
    {
        aName = rFilter;
        aMask = rMask;
    }
};

DECLARE_LIST( ImpFilterList, ImpFilterItem* )

#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif // _SV_LSTBOX_HXX

class KbdListBox : public ListBox
{
public:

                KbdListBox( Window* pParent, WinBits nStyle = WB_BORDER )
                    : ListBox ( pParent, nStyle )
                {};

virtual long    PreNotify( NotifyEvent& rNEvt );

};

class ImpPathDialog
{
    friend class ImpFileDialog;

private:
    PathDialog*         pSvPathDialog;
    Edit*               pEdit;
    FixedText*          pDirTitel;
    KbdListBox*         pDirList;
    FixedText*          pDirPath;
    ListBox*            pDriveList;
    FixedText*          pDriveTitle;
    PushButton*         pLoadBtn;
    PushButton*         pOkBtn;
    PushButton*         pCancelBtn;
    PushButton*         pHomeBtn;
    PushButton*         pNewDirBtn;

    USHORT              nOwnChilds;

    DirEntry            aPath;          // aktuell angewaehlter Pfad
    USHORT              nDirCount;      // Anzahl der Verzeichnis-
                                        // Verschachtelungen

    ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCollator >
                        xCollator;

protected:

    virtual void        UpdateEntries( const BOOL bWithDirs );
    void                UpdateDirs( const DirEntry& rTmpPath );

    BOOL                IsFileOk( const DirEntry& rDirEntry );
    void                InitControls();

    DECL_LINK(          SelectHdl, ListBox * );
    DECL_LINK(          DblClickHdl, ListBox * );
    DECL_LINK(          ClickHdl, Button * );

public:
                        ImpPathDialog( PathDialog* pDlg, WinBits nWinBits, RESOURCE_TYPE nType, BOOL bCreateDir );
    virtual             ~ImpPathDialog();

    virtual void        SetPath( const String& rPath );
    virtual void        SetPath( const Edit& rEdit );
    virtual String      GetPath() const;

    virtual void        PreExecute();
    virtual void        PostExecute();

    PathDialog*     GetPathDialog() const   { return pSvPathDialog; }

    void            SetOkButtonText( const String& rText ) { pOkBtn->SetText( rText ); }
    void            SetCancelButtonText( const String& rText ) { pCancelBtn->SetText( rText ); }

};

class ImpFileDialog : public ImpPathDialog
{
private:
    FixedText*          pFileTitel;
    ListBox*            pFileList;
    FixedText*          pTypeTitel;
    ListBox*            pTypeList;

    WildCard            aMask;          // aktuelle Maske

    ImpFilterList       aFilterList;    // Filterliste
    USHORT              nCurFilter;     // aktueller Filter

    BOOL                bOpen;          // TRUE = Open; FALSE = SAVEAS

protected:
    void                InitControls();

    String              ExtendFileName( DirEntry aEntry ) const;

    DECL_LINK(          SelectHdl, ListBox * );
    DECL_LINK(          DblClickHdl, ListBox * );
    DECL_LINK(          ClickHdl, Button * );

    virtual void        UpdateEntries( const BOOL bWithDirs );
    BOOL                IsFileOk( const DirEntry& rDirEntry );

public:
                        ImpFileDialog( PathDialog* pDlg, WinBits nWinBits, RESOURCE_TYPE nType );
    virtual             ~ImpFileDialog();

    void                AddFilter( const String& rFilter, const String& rMask );
    void                RemoveFilter( const String& rFilter );
    void                RemoveAllFilter();
    void                SetCurFilter( const String& rFilter );
    String              GetCurFilter() const;

    USHORT              GetFilterCount() const  { return (USHORT)aFilterList.Count(); }
    inline String       GetFilterName( USHORT nPos ) const;
    inline String       GetFilterType( USHORT nPos ) const;

    virtual void        SetPath( const String& rPath );
    virtual void        SetPath( const Edit& rEdit );
    virtual String      GetPath() const;

    virtual void        PreExecute();

    FileDialog*     GetFileDialog() const { return (FileDialog*)GetPathDialog(); }
};

inline String ImpFileDialog::GetFilterName( USHORT nPos ) const
{
    String aName;
    ImpFilterItem* pItem = aFilterList.GetObject( nPos );
    if ( pItem )
        aName = pItem->aName;
    return aName;
}

inline String ImpFileDialog::GetFilterType( USHORT nPos ) const
{
    String aMask;
    ImpFilterItem* pItem = aFilterList.GetObject( nPos );
    if ( pItem )
        aMask = pItem->aMask;
    return aMask;
}

class ImpSvFileDlg
{
private:
    ImpPathDialog*  pDlg;

public:
                    ImpSvFileDlg()      { pDlg = 0; }
                    ~ImpSvFileDlg()     { delete pDlg; }

    ImpPathDialog*  GetDialog() const   { return pDlg; }
    void            CreateDialog( PathDialog* pCreateFrom, WinBits nStyle, RESOURCE_TYPE nType, BOOL bCreate );

    void            SetOkButtonText( const String& rText ) { pDlg->SetOkButtonText( rText ); }  // ihr habts ja nicht anders gewollt
    void            SetCancelButtonText( const String& rText ) { pDlg->SetCancelButtonText( rText ); }

};

#endif // _FILEDLG2_HXX
<commit_msg>INTEGRATION: CWS warnings01 (1.3.62); FILE MERGED 2005/11/15 17:54:29 pl 1.3.62.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: filedlg2.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 20:59:47 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _FILEDLG2_HXX
#define _FILEDLG2_HXX

#ifndef _TOOLS_DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif
#ifndef _FSYS_HXX //autogen
#include <tools/fsys.hxx>
#endif
#ifndef _SV_BUTTON_HXX //autogen wg. PushButton
#include <vcl/button.hxx>
#endif
#ifndef _VCL_UNOHELP_HXX
#include <vcl/unohelp.hxx>
#endif

class FixedText;
class Edit;
class ListBox;
class ListBox;
class Button;

class PathDialog;
class FileDialog;
class ImpPathDialog;

struct ImpFilterItem
{
    String aName;
    String aMask;

    ImpFilterItem( const String & rFilter, const String & rMask )
    {
        aName = rFilter;
        aMask = rMask;
    }
};

DECLARE_LIST( ImpFilterList, ImpFilterItem* )

#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif // _SV_LSTBOX_HXX

class KbdListBox : public ListBox
{
public:

                KbdListBox( Window* pParent, WinBits nStyle = WB_BORDER )
                    : ListBox ( pParent, nStyle )
                {};

virtual long    PreNotify( NotifyEvent& rNEvt );

};

class ImpPathDialog
{
    friend class ImpFileDialog;

private:
    PathDialog*         pSvPathDialog;
    Edit*               pEdit;
    FixedText*          pDirTitel;
    KbdListBox*         pDirList;
    FixedText*          pDirPath;
    ListBox*            pDriveList;
    FixedText*          pDriveTitle;
    PushButton*         pLoadBtn;
    PushButton*         pOkBtn;
    PushButton*         pCancelBtn;
    PushButton*         pHomeBtn;
    PushButton*         pNewDirBtn;

    USHORT              nOwnChilds;

    DirEntry            aPath;          // aktuell angewaehlter Pfad
    USHORT              nDirCount;      // Anzahl der Verzeichnis-
                                        // Verschachtelungen

    ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCollator >
                        xCollator;

protected:

    virtual void        UpdateEntries( const BOOL bWithDirs );
    void                UpdateDirs( const DirEntry& rTmpPath );

    BOOL                IsFileOk( const DirEntry& rDirEntry );
    void                InitControls();

    DECL_LINK(          SelectHdl, ListBox * );
    DECL_LINK(          DblClickHdl, ListBox * );
    DECL_LINK(          ClickHdl, Button * );

public:
                        ImpPathDialog( PathDialog* pDlg, RESOURCE_TYPE nType, BOOL bCreateDir );
    virtual             ~ImpPathDialog();

    virtual void        SetPath( const String& rPath );
    virtual void        SetPath( const Edit& rEdit );
    virtual String      GetPath() const;

    virtual void        PreExecute();
    virtual void        PostExecute();

    PathDialog*     GetPathDialog() const   { return pSvPathDialog; }

    void            SetOkButtonText( const String& rText ) { pOkBtn->SetText( rText ); }
    void            SetCancelButtonText( const String& rText ) { pCancelBtn->SetText( rText ); }

};

class ImpFileDialog : public ImpPathDialog
{
private:
    FixedText*          pFileTitel;
    ListBox*            pFileList;
    FixedText*          pTypeTitel;
    ListBox*            pTypeList;

    WildCard            aMask;          // aktuelle Maske

    ImpFilterList       aFilterList;    // Filterliste
    USHORT              nCurFilter;     // aktueller Filter

    BOOL                bOpen;          // TRUE = Open; FALSE = SAVEAS

protected:
    void                InitControls();

    String              ExtendFileName( DirEntry aEntry ) const;

    DECL_LINK(          SelectHdl, ListBox * );
    DECL_LINK(          DblClickHdl, ListBox * );
    DECL_LINK(          ClickHdl, Button * );

    virtual void        UpdateEntries( const BOOL bWithDirs );
    BOOL                IsFileOk( const DirEntry& rDirEntry );

public:
                        ImpFileDialog( PathDialog* pDlg, WinBits nStyle, RESOURCE_TYPE nType );
    virtual             ~ImpFileDialog();

    void                AddFilter( const String& rFilter, const String& rMask );
    void                RemoveFilter( const String& rFilter );
    void                RemoveAllFilter();
    void                SetCurFilter( const String& rFilter );
    String              GetCurFilter() const;

    USHORT              GetFilterCount() const  { return (USHORT)aFilterList.Count(); }
    inline String       GetFilterName( USHORT nPos ) const;
    inline String       GetFilterType( USHORT nPos ) const;

    virtual void        SetPath( const String& rPath );
    virtual void        SetPath( const Edit& rEdit );
    virtual String      GetPath() const;

    virtual void        PreExecute();

    FileDialog*     GetFileDialog() const { return (FileDialog*)GetPathDialog(); }
};

inline String ImpFileDialog::GetFilterName( USHORT nPos ) const
{
    String aName;
    ImpFilterItem* pItem = aFilterList.GetObject( nPos );
    if ( pItem )
        aName = pItem->aName;
    return aName;
}

inline String ImpFileDialog::GetFilterType( USHORT nPos ) const
{
    String aFilterMask;
    ImpFilterItem* pItem = aFilterList.GetObject( nPos );
    if ( pItem )
        aFilterMask = pItem->aMask;
    return aFilterMask;
}

class ImpSvFileDlg
{
private:
    ImpPathDialog*  pDlg;

public:
                    ImpSvFileDlg()      { pDlg = 0; }
                    ~ImpSvFileDlg()     { delete pDlg; }

    ImpPathDialog*  GetDialog() const   { return pDlg; }
    void            CreateDialog( PathDialog* pCreateFrom, WinBits nStyle, RESOURCE_TYPE nType, BOOL bCreate );

    void            SetOkButtonText( const String& rText ) { pDlg->SetOkButtonText( rText ); }  // ihr habts ja nicht anders gewollt
    void            SetCancelButtonText( const String& rText ) { pDlg->SetCancelButtonText( rText ); }

};

#endif // _FILEDLG2_HXX
<|endoftext|>


<commit_before><commit_msg>sw: dump ruby text in nodes dump<commit_after><|endoftext|>


<commit_before>/*************************************************************************/
/*  message_queue.cpp                                                    */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#include "message_queue.h"

#include "global_config.h"
#include "script_language.h"

MessageQueue *MessageQueue::singleton = NULL;

MessageQueue *MessageQueue::get_singleton() {

	return singleton;
}

Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {

	_THREAD_SAFE_METHOD_

	int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount;

	if ((buffer_end + room_needed) >= buffer_size) {
		String type;
		if (ObjectDB::get_instance(p_id))
			type = ObjectDB::get_instance(p_id)->get_class();
		print_line("failed method: " + type + ":" + p_method + " target ID: " + itos(p_id));
		statistics();
	}

	ERR_FAIL_COND_V((buffer_end + room_needed) >= buffer_size, ERR_OUT_OF_MEMORY);
	Message *msg = memnew_placement(&buffer[buffer_end], Message);
	msg->args = p_argcount;
	msg->instance_ID = p_id;
	msg->target = p_method;
	msg->type = TYPE_CALL;
	if (p_show_error)
		msg->type |= FLAG_SHOW_ERROR;

	buffer_end += sizeof(Message);

	for (int i = 0; i < p_argcount; i++) {

		Variant *v = memnew_placement(&buffer[buffer_end], Variant);
		buffer_end += sizeof(Variant);
		*v = *p_args[i];
	}

	return OK;
}

Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {

	VARIANT_ARGPTRS;

	int argc = 0;

	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
		if (argptr[i]->get_type() == Variant::NIL)
			break;
		argc++;
	}

	return push_call(p_id, p_method, argptr, argc, false);
}

Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value) {

	_THREAD_SAFE_METHOD_

	uint8_t room_needed = sizeof(Message) + sizeof(Variant);

	if ((buffer_end + room_needed) >= buffer_size) {
		String type;
		if (ObjectDB::get_instance(p_id))
			type = ObjectDB::get_instance(p_id)->get_class();
		print_line("failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id));
		statistics();
	}

	ERR_FAIL_COND_V((buffer_end + room_needed) >= buffer_size, ERR_OUT_OF_MEMORY);

	Message *msg = memnew_placement(&buffer[buffer_end], Message);
	msg->args = 1;
	msg->instance_ID = p_id;
	msg->target = p_prop;
	msg->type = TYPE_SET;

	buffer_end += sizeof(Message);

	Variant *v = memnew_placement(&buffer[buffer_end], Variant);
	buffer_end += sizeof(Variant);
	*v = p_value;

	return OK;
}

Error MessageQueue::push_notification(ObjectID p_id, int p_notification) {

	_THREAD_SAFE_METHOD_

	ERR_FAIL_COND_V(p_notification < 0, ERR_INVALID_PARAMETER);

	uint8_t room_needed = sizeof(Message);

	if ((buffer_end + room_needed) >= buffer_size) {
		String type;
		if (ObjectDB::get_instance(p_id))
			type = ObjectDB::get_instance(p_id)->get_class();
		print_line("failed notification: " + itos(p_notification) + " target ID: " + itos(p_id));
		statistics();
	}

	ERR_FAIL_COND_V((buffer_end + room_needed) >= buffer_size, ERR_OUT_OF_MEMORY);
	Message *msg = memnew_placement(&buffer[buffer_end], Message);

	msg->type = TYPE_NOTIFICATION;
	msg->instance_ID = p_id;
	//msg->target;
	msg->notification = p_notification;

	buffer_end += sizeof(Message);

	return OK;
}

Error MessageQueue::push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {

	return push_call(p_object->get_instance_ID(), p_method, VARIANT_ARG_PASS);
}

Error MessageQueue::push_notification(Object *p_object, int p_notification) {

	return push_notification(p_object->get_instance_ID(), p_notification);
}
Error MessageQueue::push_set(Object *p_object, const StringName &p_prop, const Variant &p_value) {

	return push_set(p_object->get_instance_ID(), p_prop, p_value);
}

void MessageQueue::statistics() {

	Map<StringName, int> set_count;
	Map<int, int> notify_count;
	Map<StringName, int> call_count;
	int null_count = 0;

	uint32_t read_pos = 0;
	while (read_pos < buffer_end) {
		Message *message = (Message *)&buffer[read_pos];

		Object *target = ObjectDB::get_instance(message->instance_ID);

		if (target != NULL) {

			switch (message->type & FLAG_MASK) {

				case TYPE_CALL: {

					if (!call_count.has(message->target))
						call_count[message->target] = 0;

					call_count[message->target]++;

				} break;
				case TYPE_NOTIFICATION: {

					if (!notify_count.has(message->notification))
						notify_count[message->notification] = 0;

					notify_count[message->notification]++;

				} break;
				case TYPE_SET: {

					if (!set_count.has(message->target))
						set_count[message->target] = 0;

					set_count[message->target]++;

				} break;
			}

			//object was deleted
			//WARN_PRINT("Object was deleted while awaiting a callback")
			//should it print a warning?
		} else {

			null_count++;
		}

		read_pos += sizeof(Message);
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION)
			read_pos += sizeof(Variant) * message->args;
	}

	print_line("TOTAL BYTES: " + itos(buffer_end));
	print_line("NULL count: " + itos(null_count));

	for (Map<StringName, int>::Element *E = set_count.front(); E; E = E->next()) {

		print_line("SET " + E->key() + ": " + itos(E->get()));
	}

	for (Map<StringName, int>::Element *E = call_count.front(); E; E = E->next()) {

		print_line("CALL " + E->key() + ": " + itos(E->get()));
	}

	for (Map<int, int>::Element *E = notify_count.front(); E; E = E->next()) {

		print_line("NOTIFY " + itos(E->key()) + ": " + itos(E->get()));
	}
}

bool MessageQueue::print() {
#if 0
	uint32_t read_pos=0;
	while (read_pos < buffer_end ) {
		Message *message = (Message*)&buffer[ read_pos ];

		Object *target = ObjectDB::get_instance(message->instance_ID);
		String cname;
		String cfunc;

		if (target==NULL) {
			//object was deleted
			//WARN_PRINT("Object was deleted while awaiting a callback")
			//should it print a warning?
		} else if (message->notification>=0) {

			// messages don't expect a return value
			cfunc="notification # "+itos(message->notification);
			cname=target->get_type();

		} else if (!message->target.empty()) {

			cfunc="property:  "+message->target;
			cname=target->get_type();

		} else if (message->target) {

			cfunc=String(message->target)+"()";
			cname=target->get_type();
		}

		read_pos+=sizeof(Message);
		if (message->type!=TYPE_NOTIFICATION)
			read_pos+=sizeof(Variant)*message->args;
	}
#endif
	return false;
}

int MessageQueue::get_max_buffer_usage() const {

	return buffer_max_used;
}

void MessageQueue::_call_function(Object *p_target, const StringName &p_func, const Variant *p_args, int p_argcount, bool p_show_error) {

	const Variant **argptrs = NULL;
	if (p_argcount) {
		argptrs = (const Variant **)alloca(sizeof(Variant *) * p_argcount);
		for (int i = 0; i < p_argcount; i++) {
			argptrs[i] = &p_args[i];
		}
	}

	Variant::CallError ce;
	p_target->call(p_func, argptrs, p_argcount, ce);
	if (p_show_error && ce.error != Variant::CallError::CALL_OK) {

		ERR_PRINTS("Error calling deferred method: " + Variant::get_call_error_text(p_target, p_func, argptrs, p_argcount, ce));
	}
}

void MessageQueue::flush() {

	if (buffer_end > buffer_max_used) {
		buffer_max_used = buffer_end;
		//statistics();
	}

	uint32_t read_pos = 0;

	//using reverse locking strategy
	_THREAD_SAFE_LOCK_

	while (read_pos < buffer_end) {

		_THREAD_SAFE_UNLOCK_

		//lock on each interation, so a call can re-add itself to the message queue

		Message *message = (Message *)&buffer[read_pos];

		Object *target = ObjectDB::get_instance(message->instance_ID);

		if (target != NULL) {

			switch (message->type & FLAG_MASK) {
				case TYPE_CALL: {

					Variant *args = (Variant *)(message + 1);

					// messages don't expect a return value

					_call_function(target, message->target, args, message->args, message->type & FLAG_SHOW_ERROR);

					for (int i = 0; i < message->args; i++) {
						args[i].~Variant();
					}

				} break;
				case TYPE_NOTIFICATION: {

					// messages don't expect a return value
					target->notification(message->notification);

				} break;
				case TYPE_SET: {

					Variant *arg = (Variant *)(message + 1);
					// messages don't expect a return value
					target->set(message->target, *arg);

					arg->~Variant();
				} break;
			}
		}

		uint32_t advance = sizeof(Message);
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION)
			advance += sizeof(Variant) * message->args;
		message->~Message();

		_THREAD_SAFE_LOCK_
		read_pos += advance;
	}

	buffer_end = 0; // reset buffer
	_THREAD_SAFE_UNLOCK_
}

MessageQueue::MessageQueue() {

	ERR_FAIL_COND(singleton != NULL);
	singleton = this;

	buffer_end = 0;
	buffer_max_used = 0;
	buffer_size = GLOBAL_DEF("memory/buffers/message_queue_max_size_kb", DEFAULT_QUEUE_SIZE_KB);
	buffer_size *= 1024;
	buffer = memnew_arr(uint8_t, buffer_size);
}

MessageQueue::~MessageQueue() {

	uint32_t read_pos = 0;

	while (read_pos < buffer_end) {

		Message *message = (Message *)&buffer[read_pos];
		Variant *args = (Variant *)(message + 1);
		int argc = message->args;
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) {
			for (int i = 0; i < argc; i++)
				args[i].~Variant();
		}
		message->~Message();

		read_pos += sizeof(Message);
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION)
			read_pos += sizeof(Variant) * message->args;
	}

	singleton = NULL;
	memdelete_arr(buffer);
}
<commit_msg>Better explain out of memory error in message queue<commit_after>/*************************************************************************/
/*  message_queue.cpp                                                    */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#include "message_queue.h"

#include "global_config.h"
#include "script_language.h"

MessageQueue *MessageQueue::singleton = NULL;

MessageQueue *MessageQueue::get_singleton() {

	return singleton;
}

Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {

	_THREAD_SAFE_METHOD_

	int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount;

	if ((buffer_end + room_needed) >= buffer_size) {
		String type;
		if (ObjectDB::get_instance(p_id))
			type = ObjectDB::get_instance(p_id)->get_class();
		print_line("failed method: " + type + ":" + p_method + " target ID: " + itos(p_id));
		statistics();
		ERR_EXPLAIN("Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings");
		ERR_FAIL_V(ERR_OUT_OF_MEMORY);
	}

	Message *msg = memnew_placement(&buffer[buffer_end], Message);
	msg->args = p_argcount;
	msg->instance_ID = p_id;
	msg->target = p_method;
	msg->type = TYPE_CALL;
	if (p_show_error)
		msg->type |= FLAG_SHOW_ERROR;

	buffer_end += sizeof(Message);

	for (int i = 0; i < p_argcount; i++) {

		Variant *v = memnew_placement(&buffer[buffer_end], Variant);
		buffer_end += sizeof(Variant);
		*v = *p_args[i];
	}

	return OK;
}

Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {

	VARIANT_ARGPTRS;

	int argc = 0;

	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
		if (argptr[i]->get_type() == Variant::NIL)
			break;
		argc++;
	}

	return push_call(p_id, p_method, argptr, argc, false);
}

Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value) {

	_THREAD_SAFE_METHOD_

	uint8_t room_needed = sizeof(Message) + sizeof(Variant);

	if ((buffer_end + room_needed) >= buffer_size) {
		String type;
		if (ObjectDB::get_instance(p_id))
			type = ObjectDB::get_instance(p_id)->get_class();
		print_line("failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id));
		statistics();
		ERR_EXPLAIN("Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings");
		ERR_FAIL_V(ERR_OUT_OF_MEMORY);
	}

	Message *msg = memnew_placement(&buffer[buffer_end], Message);
	msg->args = 1;
	msg->instance_ID = p_id;
	msg->target = p_prop;
	msg->type = TYPE_SET;

	buffer_end += sizeof(Message);

	Variant *v = memnew_placement(&buffer[buffer_end], Variant);
	buffer_end += sizeof(Variant);
	*v = p_value;

	return OK;
}

Error MessageQueue::push_notification(ObjectID p_id, int p_notification) {

	_THREAD_SAFE_METHOD_

	ERR_FAIL_COND_V(p_notification < 0, ERR_INVALID_PARAMETER);

	uint8_t room_needed = sizeof(Message);

	if ((buffer_end + room_needed) >= buffer_size) {
		String type;
		if (ObjectDB::get_instance(p_id))
			type = ObjectDB::get_instance(p_id)->get_class();
		print_line("failed notification: " + itos(p_notification) + " target ID: " + itos(p_id));
		statistics();
		ERR_EXPLAIN("Message queue out of memory. Try increasing 'message_queue_size_kb' in project settings");
		ERR_FAIL_V(ERR_OUT_OF_MEMORY);
	}

	Message *msg = memnew_placement(&buffer[buffer_end], Message);

	msg->type = TYPE_NOTIFICATION;
	msg->instance_ID = p_id;
	//msg->target;
	msg->notification = p_notification;

	buffer_end += sizeof(Message);

	return OK;
}

Error MessageQueue::push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {

	return push_call(p_object->get_instance_ID(), p_method, VARIANT_ARG_PASS);
}

Error MessageQueue::push_notification(Object *p_object, int p_notification) {

	return push_notification(p_object->get_instance_ID(), p_notification);
}
Error MessageQueue::push_set(Object *p_object, const StringName &p_prop, const Variant &p_value) {

	return push_set(p_object->get_instance_ID(), p_prop, p_value);
}

void MessageQueue::statistics() {

	Map<StringName, int> set_count;
	Map<int, int> notify_count;
	Map<StringName, int> call_count;
	int null_count = 0;

	uint32_t read_pos = 0;
	while (read_pos < buffer_end) {
		Message *message = (Message *)&buffer[read_pos];

		Object *target = ObjectDB::get_instance(message->instance_ID);

		if (target != NULL) {

			switch (message->type & FLAG_MASK) {

				case TYPE_CALL: {

					if (!call_count.has(message->target))
						call_count[message->target] = 0;

					call_count[message->target]++;

				} break;
				case TYPE_NOTIFICATION: {

					if (!notify_count.has(message->notification))
						notify_count[message->notification] = 0;

					notify_count[message->notification]++;

				} break;
				case TYPE_SET: {

					if (!set_count.has(message->target))
						set_count[message->target] = 0;

					set_count[message->target]++;

				} break;
			}

			//object was deleted
			//WARN_PRINT("Object was deleted while awaiting a callback")
			//should it print a warning?
		} else {

			null_count++;
		}

		read_pos += sizeof(Message);
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION)
			read_pos += sizeof(Variant) * message->args;
	}

	print_line("TOTAL BYTES: " + itos(buffer_end));
	print_line("NULL count: " + itos(null_count));

	for (Map<StringName, int>::Element *E = set_count.front(); E; E = E->next()) {

		print_line("SET " + E->key() + ": " + itos(E->get()));
	}

	for (Map<StringName, int>::Element *E = call_count.front(); E; E = E->next()) {

		print_line("CALL " + E->key() + ": " + itos(E->get()));
	}

	for (Map<int, int>::Element *E = notify_count.front(); E; E = E->next()) {

		print_line("NOTIFY " + itos(E->key()) + ": " + itos(E->get()));
	}
}

bool MessageQueue::print() {
#if 0
	uint32_t read_pos=0;
	while (read_pos < buffer_end ) {
		Message *message = (Message*)&buffer[ read_pos ];

		Object *target = ObjectDB::get_instance(message->instance_ID);
		String cname;
		String cfunc;

		if (target==NULL) {
			//object was deleted
			//WARN_PRINT("Object was deleted while awaiting a callback")
			//should it print a warning?
		} else if (message->notification>=0) {

			// messages don't expect a return value
			cfunc="notification # "+itos(message->notification);
			cname=target->get_type();

		} else if (!message->target.empty()) {

			cfunc="property:  "+message->target;
			cname=target->get_type();

		} else if (message->target) {

			cfunc=String(message->target)+"()";
			cname=target->get_type();
		}

		read_pos+=sizeof(Message);
		if (message->type!=TYPE_NOTIFICATION)
			read_pos+=sizeof(Variant)*message->args;
	}
#endif
	return false;
}

int MessageQueue::get_max_buffer_usage() const {

	return buffer_max_used;
}

void MessageQueue::_call_function(Object *p_target, const StringName &p_func, const Variant *p_args, int p_argcount, bool p_show_error) {

	const Variant **argptrs = NULL;
	if (p_argcount) {
		argptrs = (const Variant **)alloca(sizeof(Variant *) * p_argcount);
		for (int i = 0; i < p_argcount; i++) {
			argptrs[i] = &p_args[i];
		}
	}

	Variant::CallError ce;
	p_target->call(p_func, argptrs, p_argcount, ce);
	if (p_show_error && ce.error != Variant::CallError::CALL_OK) {

		ERR_PRINTS("Error calling deferred method: " + Variant::get_call_error_text(p_target, p_func, argptrs, p_argcount, ce));
	}
}

void MessageQueue::flush() {

	if (buffer_end > buffer_max_used) {
		buffer_max_used = buffer_end;
		//statistics();
	}

	uint32_t read_pos = 0;

	//using reverse locking strategy
	_THREAD_SAFE_LOCK_

	while (read_pos < buffer_end) {

		_THREAD_SAFE_UNLOCK_

		//lock on each interation, so a call can re-add itself to the message queue

		Message *message = (Message *)&buffer[read_pos];

		Object *target = ObjectDB::get_instance(message->instance_ID);

		if (target != NULL) {

			switch (message->type & FLAG_MASK) {
				case TYPE_CALL: {

					Variant *args = (Variant *)(message + 1);

					// messages don't expect a return value

					_call_function(target, message->target, args, message->args, message->type & FLAG_SHOW_ERROR);

					for (int i = 0; i < message->args; i++) {
						args[i].~Variant();
					}

				} break;
				case TYPE_NOTIFICATION: {

					// messages don't expect a return value
					target->notification(message->notification);

				} break;
				case TYPE_SET: {

					Variant *arg = (Variant *)(message + 1);
					// messages don't expect a return value
					target->set(message->target, *arg);

					arg->~Variant();
				} break;
			}
		}

		uint32_t advance = sizeof(Message);
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION)
			advance += sizeof(Variant) * message->args;
		message->~Message();

		_THREAD_SAFE_LOCK_
		read_pos += advance;
	}

	buffer_end = 0; // reset buffer
	_THREAD_SAFE_UNLOCK_
}

MessageQueue::MessageQueue() {

	ERR_FAIL_COND(singleton != NULL);
	singleton = this;

	buffer_end = 0;
	buffer_max_used = 0;
	buffer_size = GLOBAL_DEF("memory/buffers/message_queue_max_size_kb", DEFAULT_QUEUE_SIZE_KB);
	buffer_size *= 1024;
	buffer = memnew_arr(uint8_t, buffer_size);
}

MessageQueue::~MessageQueue() {

	uint32_t read_pos = 0;

	while (read_pos < buffer_end) {

		Message *message = (Message *)&buffer[read_pos];
		Variant *args = (Variant *)(message + 1);
		int argc = message->args;
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) {
			for (int i = 0; i < argc; i++)
				args[i].~Variant();
		}
		message->~Message();

		read_pos += sizeof(Message);
		if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION)
			read_pos += sizeof(Variant) * message->args;
	}

	singleton = NULL;
	memdelete_arr(buffer);
}
<|endoftext|>


<commit_before>// Gridding algoithm, adopted from bilateral_grid demo app.
// There's nothing left from bilateral_grid except ideas and typical Halide idioms.

#include "Halide.h"
#include <stdio.h>

using namespace Halide;

int main(int argc, char **argv) {
    ImageParam UVW(Float(64), 4);    // second dimension is used for U, V and W parts. So it should be Nx3 sized.

    // Constant supersample factor.
    Expr supersampleFactor = 8;

    // The Omega - telescope view angle.
    Expr Omega = pi/2;

    // Two dimensional image for prolate spheroidal wave function. Last dimension is fixed to 2.
    ImageParam PSWF(Float(64),3);

    Var pswfKernelHalf("pswfKernelHalf");

    // pswf kernel image height and width are odd, 2N+1. To recover the half, and not to overflow image bounds,
    // we first subtract 1 and only then divide by 2. It have to work for 2N+1 and is safe for even values.
    // (albeit incorrect).
    pswfKernelHalf = (PSWF.extent(0)-1) / 2;

    // Iterator within UVW triples.
    RDom uvwRange (0, UVW.extent(0), 0, UVW.extent(1), 0, UVW.extent(2));

    Var timestep("timestep");
    Var baseline("baseline");
    Var channel("channel");

    baseline = uvwRange.x;
    timestep = uvmRange.y;
    timestep = uvwRange.z;

    // fetch the values.
    Var U("U");
    U = UVW(baseline, timestep, channel, 0);
    Var V("V");
    V = UVW(baseline, timestep, channel, 1);
    Var W("W");
    W = UVW(baseline, timestep, channel, 2);

    Expr intU = cast<int>U;
    Expr intV = case<int>V;

    Expr supersampleU = cast<int>(supersampleFactor*(U - intU));
    Expr supersampleV = cast<int>(supersampleFactor*(V - intV));

    // Computation of kernel width.
    Expr onePercent = 0.01;
    Expr wOmegaBy2 = W*Omega/2;
    Expr GKernelWidth = sqrt(wOmegaBy2*(wOmegaBy2 + pi*onePercent/sqrt(w)));
    Expr GKernelWidthInt = cast<int>(GKernelWidth+0.5);

    // Range over kernel space. It is two dimensional, to account for U and V.
    RDom GUVRange (-GKernelWidthInt, GKernelWidthInt+1, -GKernelWidthInt, GKernelWidthInt+1);

    Var GU("GU");
    Var GV("GV");

    GU = GUVRange.x;
    GV = GUVRange.y;

    // Range over PSWF space.
    RDom pswfRange(-pswfKernelHalf, pswfKernelHalf+1, -pswfKernelHalf, pswfKernelHalf+1);

    Var PSWFU("PSWFU");
    Var PSWFV("PSWFV");

    PSWFU = pswfRange.x;
    PSWFV = pswfRange.y;

    // The G kernel.
    Func G("G");

    // !!! XXX FIXME !!! XXX FIXME
    G(GU,GV) = 1-G*0.01-U*0.01;

    // The computation of the result.
    Func result("result");
    var rU("rU");
    Var rV("rV");

    // computing the result
    rU = intU + GU+PSWFU;
    rU = intV + GV+PSWFV;

    result(rU, rV) = 0.0;
    result(rU, rV) += PSWF(PSWFU, PSWFV)*G(GU,GV); // This product can be cached. We also can drop assignment to zero and only update image.

    return 0;
}

<commit_msg>Gridding mostly done, going to compile and test.<commit_after>// Gridding algoithm, adopted from bilateral_grid demo app.
// There's nothing left from bilateral_grid except ideas and typical Halide idioms.

#include "Halide.h"
#include <stdio.h>

using namespace Halide;

int main(int argc, char **argv) {
    ImageParam UVW(Float(64), 4);    // second dimension is used for U, V and W parts. So it should be Nx3 sized.

    // Constant supersample factor.
    Expr supersampleFactor = 8;

    // The Omega - telescope view angle.
    Expr Omega = pi/2;

    // Two dimensional image for prolate spheroidal wave function. Last dimension is fixed to 2.
    ImageParam PSWF(Float(64),3);

    Var pswfKernelHalf("pswfKernelHalf");

    // pswf kernel image height and width are odd, 2N+1. To recover the half, and not to overflow image bounds,
    // we first subtract 1 and only then divide by 2. It have to work for 2N+1 and is safe for even values.
    // (albeit incorrect).
    pswfKernelHalf = (PSWF.extent(0)-1) / 2;

    // Iterator within UVW triples.
    RDom uvwRange (0, UVW.extent(0), 0, UVW.extent(1), 0, UVW.extent(2));

    Var timestep("timestep");
    Var baseline("baseline");
    Var channel("channel");

    baseline = uvwRange.x;
    timestep = uvmRange.y;
    timestep = uvwRange.z;

    // fetch the values.
    Var U("U");
    U = UVW(baseline, timestep, channel, 0);
    Var V("V");
    V = UVW(baseline, timestep, channel, 1);
    Var W("W");
    W = UVW(baseline, timestep, channel, 2);

    Expr intU = cast<int>U;
    Expr intV = case<int>V;

    Expr supersampleU = cast<int>(supersampleFactor*(U - intU));
    Expr supersampleV = cast<int>(supersampleFactor*(V - intV));

    // Computation of kernel width.
    Expr onePercent = 0.01;
    Expr wOmegaBy2 = W*Omega/2;
    Expr GKernelWidth = sqrt(wOmegaBy2*(wOmegaBy2 + pi*onePercent/sqrt(w)));
    Expr GKernelWidthInt = cast<int>(GKernelWidth+0.5);

    // Range over kernel space. It is two dimensional, to account for U and V.
    RDom GUVRange (-GKernelWidthInt, GKernelWidthInt+1, -GKernelWidthInt, GKernelWidthInt+1);

    Var GU("GU");
    Var GV("GV");

    GU = GUVRange.x;
    GV = GUVRange.y;

    // Range over PSWF space.
    RDom pswfRange(-pswfKernelHalf, pswfKernelHalf+1, -pswfKernelHalf, pswfKernelHalf+1);

    Var PSWFU("PSWFU");
    Var PSWFV("PSWFV");

    PSWFU = pswfRange.x;
    PSWFV = pswfRange.y;

    // The G kernel.
    Func G("G");

    // !!! XXX FIXME !!! XXX FIXME
    G(GU,GV) = 1-G*0.01-U*0.01;

    // The computation of the result.
    Func gridding("gridding");
    var rU("rU");
    Var rV("rV");

    // computing the result
    rU = intU + GU+PSWFU;
    rU = intV + GV+PSWFV;

    gridding(rU, rV) = 0.0;
    gridding(rU, rV) += PSWF(PSWFU, PSWFV)*G(GU,GV); // This product can be cached. We also can drop assignment to zero and only update image.

    Target compile_target = get_target_from_environment();
    gridding.compile_to_file("gridding_compiled", UVW, PSWF, compile_target);

    return 0;
}

<|endoftext|>


<commit_before><commit_msg>Page Break: Make the line control thicker to ease fade in/out<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "native_client/src/include/portability.h"

#if NACL_OSX
#include <crt_externs.h>
#endif

#ifdef _WIN64  /* TODO(gregoryd): remove this when win64 issues are fixed */
#define NACL_NO_INLINE
#endif

EXTERN_C_BEGIN
#include "native_client/src/shared/platform/nacl_sync.h"
#include "native_client/src/shared/platform/nacl_sync_checked.h"
#include "native_client/src/trusted/service_runtime/nacl_globals.h"
#include "native_client/src/trusted/service_runtime/expiration.h"
#include "native_client/src/trusted/service_runtime/nacl_app.h"
#include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"
#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
EXTERN_C_END

int verbosity = 0;

#ifdef __GNUC__

/*
 * GDB's canonical overlay managment routine.
 * We need its symbol in the symbol table so don't inline it.
 * TODO(dje): add some explanation for the non-GDB person.
 */

static void __attribute__ ((noinline)) _ovly_debug_event (void) {
  /*
   * The asm volatile is here as instructed by the GCC docs.
   * It's not enough to declare a function noinline.
   * GCC will still look inside the function to see if it's worth calling.
   */
  asm volatile ("");
}

#endif

static void StopForDebuggerInit(const struct NaClApp *state) {
  /* Put xlate_base in a place where gdb can find it.  */
  nacl_global_xlate_base = state->mem_start;

#ifdef __GNUC__
  _ovly_debug_event();
#endif
}

int SelMain(const int desc, const NaClHandle handle) {
  char *av[1];
  int ac = 1;

  char                          **envp;
  struct NaClApp                state;
  char                          *nacl_file = 0;
  int                           main_thread_only = 1;
  int                           export_addr_to = -2;

  struct NaClApp                *nap;

  NaClErrorCode                 errcode;

  int                           ret_code = 1;
#if NACL_OSX
  // Mac dynamic libraries cannot access the environ variable directly.
  envp = *_NSGetEnviron();
#else
  extern char                   **environ;
  envp = environ;
#endif

  NaClAllModulesInit();

  /* used to be -P */
  NaClSrpcFileDescriptor = desc;
  /* used to be -X */
  export_addr_to = desc;

  /* to be passed to NaClMain, eventually... */
  av[0] = const_cast<char*>("NaClMain");

  if (!NaClAppCtor(&state)) {
    fprintf(stderr, "Error while constructing app state\n");
    goto done_file_dtor;
  }

  state.restrict_to_main_thread = main_thread_only;

  nap = &state;
  errcode = LOAD_OK;

  /* import IMC handle - used to be "-i" */
  NaClAddImcHandle(nap, handle, desc);

  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure this operating system platform is supported.
   */
  if (!NaClOsIsSupported()) {
    errcode = LOAD_UNSUPPORTED_OS_PLATFORM;
    nap->module_load_status = errcode;
    fprintf(stderr, "Error while loading \"%s\": %s\n",
            nacl_file,
            NaClErrorString(errcode));
  }

  /* Give debuggers a well known point at which xlate_base is known.  */
  StopForDebuggerInit(&state);

  /*
   * If export_addr_to is set to a non-negative integer, we create a
   * bound socket and socket address pair and bind the former to
   * descriptor 3 and the latter to descriptor 4.  The socket address
   * is written out to the export_addr_to descriptor.
   *
   * The service runtime also accepts a connection on the bound socket
   * and spawns a secure command channel thread to service it.
   *
   * If export_addr_to is -1, we only create the bound socket and
   * socket address pair, and we do not export to an IMC socket.  This
   * use case is typically only used in testing, where we only "dump"
   * the socket address to stdout or similar channel.
   */
  if (-2 < export_addr_to) {
    NaClCreateServiceSocket(nap);
    if (0 <= export_addr_to) {
      NaClSendServiceAddressTo(nap, export_addr_to);
      /*
       * NB: spawns a thread that uses the command channel.  we do
       * this after NaClAppLoadFile so that NaClApp object is more
       * fully populated.  Hereafter any changes to nap should be done
       * while holding locks.
       */
      NaClSecureCommandChannel(nap);
    }
  }

  NaClXMutexLock(&nap->mu);
  nap->module_load_status = LOAD_OK;
  NaClXCondVarBroadcast(&nap->cv);
  NaClXMutexUnlock(&nap->mu);

  if (NULL != nap->secure_channel) {
    /*
     * wait for start_module RPC call on secure channel thread.
     */
    NaClWaitForModuleStartStatusCall(nap);
  }

  /*
   * error reporting done; can quit now if there was an error earlier.
   */
  if (LOAD_OK != errcode) {
    goto done;
  }

  /*
   * only nap->ehdrs.e_entry is usable, no symbol table is
   * available.
   */
  if (!NaClCreateMainThread(nap,
                            ac,
                            av,
                            envp)) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  ret_code = NaClWaitForMainThreadToExit(nap);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  return ret_code;

 done:
  fflush(stdout);

  NaClAppDtor(&state);

 done_file_dtor:
  fflush(stdout);

  NaClAllModulesFini();

  return ret_code;
}

<commit_msg>Make _ovly_debug_event extern "C" for nacl-gdb<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "native_client/src/include/portability.h"

#if NACL_OSX
#include <crt_externs.h>
#endif

#ifdef _WIN64  /* TODO(gregoryd): remove this when win64 issues are fixed */
#define NACL_NO_INLINE
#endif

EXTERN_C_BEGIN
#include "native_client/src/shared/platform/nacl_sync.h"
#include "native_client/src/shared/platform/nacl_sync_checked.h"
#include "native_client/src/trusted/service_runtime/nacl_globals.h"
#include "native_client/src/trusted/service_runtime/expiration.h"
#include "native_client/src/trusted/service_runtime/nacl_app.h"
#include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"
#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
EXTERN_C_END

int verbosity = 0;

#ifdef __GNUC__

/*
 * GDB's canonical overlay managment routine.
 * We need its symbol in the symbol table so don't inline it.
 * Note: _ovly_debug_event has to be an unmangled 'C' style symbol.
 * TODO(dje): add some explanation for the non-GDB person.
 */
EXTERN_C_BEGIN
static void __attribute__ ((noinline)) _ovly_debug_event (void) {
  /*
   * The asm volatile is here as instructed by the GCC docs.
   * It's not enough to declare a function noinline.
   * GCC will still look inside the function to see if it's worth calling.
   */
  asm volatile ("");
}
EXTERN_C_END

#endif

static void StopForDebuggerInit(const struct NaClApp *state) {
  /* Put xlate_base in a place where gdb can find it.  */
  nacl_global_xlate_base = state->mem_start;

#ifdef __GNUC__
  _ovly_debug_event();
#endif
}

int SelMain(const int desc, const NaClHandle handle) {
  char *av[1];
  int ac = 1;

  char                          **envp;
  struct NaClApp                state;
  char                          *nacl_file = 0;
  int                           main_thread_only = 1;
  int                           export_addr_to = -2;

  struct NaClApp                *nap;

  NaClErrorCode                 errcode;

  int                           ret_code = 1;
#if NACL_OSX
  // Mac dynamic libraries cannot access the environ variable directly.
  envp = *_NSGetEnviron();
#else
  extern char                   **environ;
  envp = environ;
#endif

  NaClAllModulesInit();

  /* used to be -P */
  NaClSrpcFileDescriptor = desc;
  /* used to be -X */
  export_addr_to = desc;

  /* to be passed to NaClMain, eventually... */
  av[0] = const_cast<char*>("NaClMain");

  if (!NaClAppCtor(&state)) {
    fprintf(stderr, "Error while constructing app state\n");
    goto done_file_dtor;
  }

  state.restrict_to_main_thread = main_thread_only;

  nap = &state;
  errcode = LOAD_OK;

  /* import IMC handle - used to be "-i" */
  NaClAddImcHandle(nap, handle, desc);

  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure this operating system platform is supported.
   */
  if (!NaClOsIsSupported()) {
    errcode = LOAD_UNSUPPORTED_OS_PLATFORM;
    nap->module_load_status = errcode;
    fprintf(stderr, "Error while loading \"%s\": %s\n",
            nacl_file,
            NaClErrorString(errcode));
  }

  /* Give debuggers a well known point at which xlate_base is known.  */
  StopForDebuggerInit(&state);

  /*
   * If export_addr_to is set to a non-negative integer, we create a
   * bound socket and socket address pair and bind the former to
   * descriptor 3 and the latter to descriptor 4.  The socket address
   * is written out to the export_addr_to descriptor.
   *
   * The service runtime also accepts a connection on the bound socket
   * and spawns a secure command channel thread to service it.
   *
   * If export_addr_to is -1, we only create the bound socket and
   * socket address pair, and we do not export to an IMC socket.  This
   * use case is typically only used in testing, where we only "dump"
   * the socket address to stdout or similar channel.
   */
  if (-2 < export_addr_to) {
    NaClCreateServiceSocket(nap);
    if (0 <= export_addr_to) {
      NaClSendServiceAddressTo(nap, export_addr_to);
      /*
       * NB: spawns a thread that uses the command channel.  we do
       * this after NaClAppLoadFile so that NaClApp object is more
       * fully populated.  Hereafter any changes to nap should be done
       * while holding locks.
       */
      NaClSecureCommandChannel(nap);
    }
  }

  NaClXMutexLock(&nap->mu);
  nap->module_load_status = LOAD_OK;
  NaClXCondVarBroadcast(&nap->cv);
  NaClXMutexUnlock(&nap->mu);

  if (NULL != nap->secure_channel) {
    /*
     * wait for start_module RPC call on secure channel thread.
     */
    NaClWaitForModuleStartStatusCall(nap);
  }

  /*
   * error reporting done; can quit now if there was an error earlier.
   */
  if (LOAD_OK != errcode) {
    goto done;
  }

  /*
   * only nap->ehdrs.e_entry is usable, no symbol table is
   * available.
   */
  if (!NaClCreateMainThread(nap,
                            ac,
                            av,
                            envp)) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  ret_code = NaClWaitForMainThreadToExit(nap);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  return ret_code;

 done:
  fflush(stdout);

  NaClAppDtor(&state);

 done_file_dtor:
  fflush(stdout);

  NaClAllModulesFini();

  return ret_code;
}

<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021
             — Vladimír Vondruš <mosra@centrum.cz>
        2021 — Pablo Escobar <mail@rvrs.in>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Assert.h>
#include <Corrade/PluginManager/Manager.h>
#include <Magnum/Magnum.h>
#include <Magnum/ImageView.h>
#include <Magnum/PixelFormat.h>
#include <Magnum/Math/Color.h>
#include <Magnum/ShaderTools/AbstractConverter.h>
#include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Vk/Assert.h>
#include <Magnum/Vk/BufferCreateInfo.h>
#include <Magnum/Vk/CommandBuffer.h>
#include <Magnum/Vk/CommandPoolCreateInfo.h>
#include <Magnum/Vk/DeviceCreateInfo.h>
#include <Magnum/Vk/DeviceProperties.h>
#include <Magnum/Vk/Fence.h>
#include <Magnum/Vk/FramebufferCreateInfo.h>
#include <Magnum/Vk/ImageCreateInfo.h>
#include <Magnum/Vk/ImageViewCreateInfo.h>
#include <Magnum/Vk/InstanceCreateInfo.h>
#include <Magnum/Vk/Memory.h>
#include <Magnum/Vk/Queue.h>
#include <Magnum/Vk/RenderPassCreateInfo.h>
#include <Magnum/Vk/ShaderCreateInfo.h>
#include <MagnumExternal/Vulkan/flextVkGlobal.h>

using namespace Corrade::Containers::Literals;
using namespace Magnum;
using namespace Magnum::Math::Literals;

int main(int argc, char** argv) {
    /* Create an instance */
    Vk::Instance instance{Vk::InstanceCreateInfo{argc, argv}
        .setApplicationInfo("Magnum Vulkan Triangle Example"_s, {})};

    /* Create a device with a graphics queue */
    Vk::Queue queue{NoCreate};
    Vk::Device device{instance, Vk::DeviceCreateInfo{Vk::pickDevice(instance)}
        .addQueues(Vk::QueueFlag::Graphics, {0.0f}, {queue})};

    /* Allocate a command buffer */
    Vk::CommandPool commandPool{device, Vk::CommandPoolCreateInfo{
        device.properties().pickQueueFamily(Vk::QueueFlag::Graphics)}};
    Vk::CommandBuffer cmd = commandPool.allocate();

    device.populateGlobalFunctionPointers();

    /* Render pass */
    Vk::RenderPass renderPass{device, Vk::RenderPassCreateInfo{}
        .setAttachments({
            Vk::AttachmentDescription{PixelFormat::RGBA8Srgb,
                Vk::AttachmentLoadOperation::Clear,
                Vk::AttachmentStoreOperation::Store,
                Vk::ImageLayout::Undefined,
                Vk::ImageLayout::ColorAttachment
            }
        })
        .addSubpass(Vk::SubpassDescription{}
            .setColorAttachments({
                Vk::AttachmentReference{0, Vk::ImageLayout::ColorAttachment}
            })
        )
    };

    /* Framebuffer image. Allocate with linear tiling as we want to download it
       later. */
    Vk::Image image{NoCreate};
    {
        Vk::ImageCreateInfo2D info{Vk::ImageUsage::ColorAttachment,
            PixelFormat::RGBA8Srgb, {800, 600}, 1};
        info->tiling = VK_IMAGE_TILING_LINEAR;
        image = Vk::Image{device, info, Vk::MemoryFlag::HostVisible};
    }

    Vk::ImageView color{device, Vk::ImageViewCreateInfo2D{image}};

    /* Vertex buffer */
    Vk::Buffer buffer{device, Vk::BufferCreateInfo{
            Vk::BufferUsage::VertexBuffer,
            3*2*4*4 /* Three vertices, each is four-element pos & color */
        }, Vk::MemoryFlag::HostVisible};
    {
        /* Fill the data */
        /** @todo arrayCast for an array rvalue */
        Containers::Array<char, Vk::MemoryMapDeleter> data = buffer.dedicatedMemory().map();
        auto view = Containers::arrayCast<Vector4>(data);
        view[0] = {-0.5f, -0.5f, 0.0f, 1.0f}; /* Left vertex, red color */
        view[1] = 0xff0000ff_srgbaf;
        view[2] = { 0.5f, -0.5f, 0.0f, 1.0f}; /* Right vertex, green color */
        view[3] = 0x00ff00ff_srgbaf;
        view[4] = { 0.0f,  0.5f, 0.0f, 1.0f}; /* Top vertex, blue color */
        view[5] = 0x0000ffff_srgbaf;
    }

    /* Framebuffer */
    Vk::Framebuffer framebuffer{device, Vk::FramebufferCreateInfo{renderPass, {
        color
    }, {800, 600}}};

    /* Create the shader */
    constexpr Containers::StringView assembly = R"(
               OpCapability Shader
               OpMemoryModel Logical GLSL450

; Function %1 is vertex shader and has %12, %13 as input and %15, %16 as output
               OpEntryPoint Vertex %1 "ver" %12 %13 %gl_Position %16
; Function %2 is fragment shader and has %5 as input and %6 as output
               OpEntryPoint Fragment %2 "fra" %5 %6
               OpExecutionMode %2 OriginUpperLeft

; Input/output layouts
               OpDecorate %12 Location 0
               OpDecorate %13 Location 1
               OpDecorate %gl_Position BuiltIn Position
               OpDecorate %16 Location 0
               OpDecorate %5 Location 0
               OpDecorate %6 Location 0

; Types
       %void = OpTypeVoid
          %8 = OpTypeFunction %void
      %float = OpTypeFloat 32
    %v4float = OpTypeVector %float 4
%_ptr_Input_v4float = OpTypePointer Input %v4float
         %12 = OpVariable %_ptr_Input_v4float Input
         %13 = OpVariable %_ptr_Input_v4float Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%gl_Position = OpVariable %_ptr_Output_v4float Output
         %16 = OpVariable %_ptr_Output_v4float Output
          %5 = OpVariable %_ptr_Input_v4float Input
          %6 = OpVariable %_ptr_Output_v4float Output

; %1 = void ver()
          %1 = OpFunction %void None %8
         %33 = OpLabel
         %30 = OpLoad %v4float %12
         %31 = OpLoad %v4float %13
               OpStore %gl_Position %30
               OpStore %16 %31
               OpReturn
               OpFunctionEnd

; %2 = void fra()
          %2 = OpFunction %void None %8
         %34 = OpLabel
         %32 = OpLoad %v4float %5
               OpStore %6 %32
               OpReturn
               OpFunctionEnd
)"_s;
    Vk::Shader shader{device, Vk::ShaderCreateInfo{
        CORRADE_INTERNAL_ASSERT_EXPRESSION(CORRADE_INTERNAL_ASSERT_EXPRESSION(
            PluginManager::Manager<ShaderTools::AbstractConverter>{}.loadAndInstantiate("SpirvAssemblyToSpirvShaderConverter")
        )->convertDataToData({}, assembly))}};

    /* Pipeline layout */
    VkPipelineLayout pipelineLayout;
    {
        VkPipelineLayoutCreateInfo info{};
        info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        info.setLayoutCount = 0;
        info.pushConstantRangeCount = 0;
        MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkCreatePipelineLayout(device, &info, nullptr, &pipelineLayout));
    }

    /* Create a graphics pipeline */
    VkPipeline pipeline;
    {
        VkVertexInputBindingDescription binding{};
        binding.binding = 0;
        binding.stride = 2*4*4;

        VkVertexInputAttributeDescription attributes[2]{};
        attributes[0].location = 0; /* position attribute */
        attributes[0].binding = binding.binding;
        attributes[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
        attributes[0].offset = 0;
        attributes[1].location = 1; /* color attribute */
        attributes[1].binding = binding.binding;
        attributes[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
        attributes[1].offset = 4*4;

        VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
        vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
        vertexInputInfo.vertexBindingDescriptionCount = 1;
        vertexInputInfo.pVertexBindingDescriptions = &binding;
        vertexInputInfo.vertexAttributeDescriptionCount = 2;
        vertexInputInfo.pVertexAttributeDescriptions = attributes;

        VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo{};
        inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
        inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

        VkViewport viewport{};
        viewport.width = 800.0f;
        viewport.height = 600.0f;
        viewport.maxDepth = 1.0f;

        VkRect2D scissor{{}, {800, 600}};

        VkPipelineViewportStateCreateInfo viewportInfo{};
        viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
        viewportInfo.viewportCount = 1;
        viewportInfo.pViewports = &viewport;
        viewportInfo.scissorCount = 1;
        viewportInfo.pScissors = &scissor;

        VkPipelineRasterizationStateCreateInfo rasterizationInfo{};
        rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
        rasterizationInfo.lineWidth = 1.0f;
        /* the zero-filled defaults are good enough apparently */

        VkPipelineMultisampleStateCreateInfo multisampleInfo{};
        multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
        multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

        VkPipelineColorBlendAttachmentState blend{};
        blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT|
                               VK_COLOR_COMPONENT_G_BIT|
                               VK_COLOR_COMPONENT_B_BIT|
                               VK_COLOR_COMPONENT_A_BIT;
        VkPipelineColorBlendStateCreateInfo colorBlendInfo{};
        colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
        colorBlendInfo.attachmentCount = 1;
        colorBlendInfo.pAttachments = &blend;

        VkPipelineShaderStageCreateInfo stages[2]{};
        stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
        stages[0].module = shader;
        stages[0].pName = "ver";
        stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
        stages[1].module = shader;
        stages[1].pName = "fra";

        VkGraphicsPipelineCreateInfo info{};
        info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
        info.stageCount = 2;
        info.pStages = stages;
        info.pVertexInputState = &vertexInputInfo;
        info.pInputAssemblyState = &inputAssemblyInfo;
        info.pViewportState = &viewportInfo;
        info.pRasterizationState = &rasterizationInfo;
        info.pMultisampleState = &multisampleInfo;
        info.pColorBlendState = &colorBlendInfo;
        info.layout = pipelineLayout;
        info.renderPass = renderPass;
        info.subpass = 0;
        MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkCreateGraphicsPipelines(device, nullptr, 1, &info, nullptr, &pipeline));
    }

    /* Begin recording */
    cmd.begin();

    /* Begin a render pass. Converts the framebuffer attachment from Undefined
       to ColorAttachment layout and clears it. */
    cmd.beginRenderPass(Vk::RenderPassBeginInfo{renderPass, framebuffer}
           .clearColor(0, 0x1f1f1f_srgbf));

    /* Bind the pipeline */
    vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

    /* Bind the vertex buffer */
    {
        const VkDeviceSize offset = 0;
        const VkBuffer handle = buffer;
        vkCmdBindVertexBuffers(cmd, 0, 1, &handle, &offset);
    }

    /* Draw the triangle */
    vkCmdDraw(cmd, 3, 1, 0, 0);

    /* End recording */
    cmd.endRenderPass()
       .end();

    /* Submit the command buffer and wait until done */
    Vk::Fence fence{device};
    queue.submit({Vk::SubmitInfo{}.setCommandBuffers({cmd})}, fence);
    fence.wait();

    /* Read the image back */
    CORRADE_INTERNAL_ASSERT_EXPRESSION(
        PluginManager::Manager<Trade::AbstractImageConverter>{}
            .loadAndInstantiate("AnyImageConverter")
    )->exportToFile(ImageView2D{
        PixelFormat::RGBA8Unorm, {800, 600},
        image.dedicatedMemory().mapRead()}, "image.png");
    Debug{} << "Saved an image to image.png";

    /* Clean up */
    vkDestroyPipeline(device, pipeline, nullptr);
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
}
<commit_msg>triangle-vulkan: minor formatting.<commit_after>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021
             — Vladimír Vondruš <mosra@centrum.cz>
        2021 — Pablo Escobar <mail@rvrs.in>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Assert.h>
#include <Corrade/PluginManager/Manager.h>
#include <Magnum/Magnum.h>
#include <Magnum/ImageView.h>
#include <Magnum/PixelFormat.h>
#include <Magnum/Math/Color.h>
#include <Magnum/ShaderTools/AbstractConverter.h>
#include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Vk/Assert.h>
#include <Magnum/Vk/BufferCreateInfo.h>
#include <Magnum/Vk/CommandBuffer.h>
#include <Magnum/Vk/CommandPoolCreateInfo.h>
#include <Magnum/Vk/DeviceCreateInfo.h>
#include <Magnum/Vk/DeviceProperties.h>
#include <Magnum/Vk/Fence.h>
#include <Magnum/Vk/FramebufferCreateInfo.h>
#include <Magnum/Vk/ImageCreateInfo.h>
#include <Magnum/Vk/ImageViewCreateInfo.h>
#include <Magnum/Vk/InstanceCreateInfo.h>
#include <Magnum/Vk/Memory.h>
#include <Magnum/Vk/Queue.h>
#include <Magnum/Vk/RenderPassCreateInfo.h>
#include <Magnum/Vk/ShaderCreateInfo.h>
#include <MagnumExternal/Vulkan/flextVkGlobal.h>

using namespace Corrade::Containers::Literals;
using namespace Magnum;
using namespace Magnum::Math::Literals;

int main(int argc, char** argv) {
    /* Create an instance */
    Vk::Instance instance{Vk::InstanceCreateInfo{argc, argv}
        .setApplicationInfo("Magnum Vulkan Triangle Example"_s, {})};

    /* Create a device with a graphics queue */
    Vk::Queue queue{NoCreate};
    Vk::Device device{instance, Vk::DeviceCreateInfo{Vk::pickDevice(instance)}
        .addQueues(Vk::QueueFlag::Graphics, {0.0f}, {queue})};

    /* Allocate a command buffer */
    Vk::CommandPool commandPool{device, Vk::CommandPoolCreateInfo{
        device.properties().pickQueueFamily(Vk::QueueFlag::Graphics)}};
    Vk::CommandBuffer cmd = commandPool.allocate();

    device.populateGlobalFunctionPointers();

    /* Render pass */
    Vk::RenderPass renderPass{device, Vk::RenderPassCreateInfo{}
        .setAttachments({
            Vk::AttachmentDescription{PixelFormat::RGBA8Srgb,
                Vk::AttachmentLoadOperation::Clear,
                Vk::AttachmentStoreOperation::Store,
                Vk::ImageLayout::Undefined,
                Vk::ImageLayout::ColorAttachment
            }
        })
        .addSubpass(Vk::SubpassDescription{}
            .setColorAttachments({
                Vk::AttachmentReference{0, Vk::ImageLayout::ColorAttachment}
            })
        )
    };

    /* Framebuffer image. Allocate with linear tiling as we want to download it
       later. */
    Vk::Image image{NoCreate};
    {
        Vk::ImageCreateInfo2D info{Vk::ImageUsage::ColorAttachment,
            PixelFormat::RGBA8Srgb, {800, 600}, 1};
        info->tiling = VK_IMAGE_TILING_LINEAR;
        image = Vk::Image{device, info, Vk::MemoryFlag::HostVisible};
    }

    Vk::ImageView color{device, Vk::ImageViewCreateInfo2D{image}};

    /* Vertex buffer */
    Vk::Buffer buffer{device, Vk::BufferCreateInfo{
        Vk::BufferUsage::VertexBuffer,
        3*2*4*4 /* Three vertices, each is four-element pos & color */
    }, Vk::MemoryFlag::HostVisible};
    {
        /* Fill the data */
        /** @todo arrayCast for an array rvalue */
        Containers::Array<char, Vk::MemoryMapDeleter> data = buffer.dedicatedMemory().map();
        auto view = Containers::arrayCast<Vector4>(data);
        view[0] = {-0.5f, -0.5f, 0.0f, 1.0f}; /* Left vertex, red color */
        view[1] = 0xff0000ff_srgbaf;
        view[2] = { 0.5f, -0.5f, 0.0f, 1.0f}; /* Right vertex, green color */
        view[3] = 0x00ff00ff_srgbaf;
        view[4] = { 0.0f,  0.5f, 0.0f, 1.0f}; /* Top vertex, blue color */
        view[5] = 0x0000ffff_srgbaf;
    }

    /* Framebuffer */
    Vk::Framebuffer framebuffer{device, Vk::FramebufferCreateInfo{renderPass, {
        color
    }, {800, 600}}};

    /* Create the shader */
    constexpr Containers::StringView assembly = R"(
               OpCapability Shader
               OpMemoryModel Logical GLSL450

; Function %1 is vertex shader and has %12, %13 as input and %15, %16 as output
               OpEntryPoint Vertex %1 "ver" %12 %13 %gl_Position %16
; Function %2 is fragment shader and has %5 as input and %6 as output
               OpEntryPoint Fragment %2 "fra" %5 %6
               OpExecutionMode %2 OriginUpperLeft

; Input/output layouts
               OpDecorate %12 Location 0
               OpDecorate %13 Location 1
               OpDecorate %gl_Position BuiltIn Position
               OpDecorate %16 Location 0
               OpDecorate %5 Location 0
               OpDecorate %6 Location 0

; Types
       %void = OpTypeVoid
          %8 = OpTypeFunction %void
      %float = OpTypeFloat 32
    %v4float = OpTypeVector %float 4
%_ptr_Input_v4float = OpTypePointer Input %v4float
         %12 = OpVariable %_ptr_Input_v4float Input
         %13 = OpVariable %_ptr_Input_v4float Input
%_ptr_Output_v4float = OpTypePointer Output %v4float
%gl_Position = OpVariable %_ptr_Output_v4float Output
         %16 = OpVariable %_ptr_Output_v4float Output
          %5 = OpVariable %_ptr_Input_v4float Input
          %6 = OpVariable %_ptr_Output_v4float Output

; %1 = void ver()
          %1 = OpFunction %void None %8
         %33 = OpLabel
         %30 = OpLoad %v4float %12
         %31 = OpLoad %v4float %13
               OpStore %gl_Position %30
               OpStore %16 %31
               OpReturn
               OpFunctionEnd

; %2 = void fra()
          %2 = OpFunction %void None %8
         %34 = OpLabel
         %32 = OpLoad %v4float %5
               OpStore %6 %32
               OpReturn
               OpFunctionEnd
)"_s;
    Vk::Shader shader{device, Vk::ShaderCreateInfo{
        CORRADE_INTERNAL_ASSERT_EXPRESSION(CORRADE_INTERNAL_ASSERT_EXPRESSION(
            PluginManager::Manager<ShaderTools::AbstractConverter>{}.loadAndInstantiate("SpirvAssemblyToSpirvShaderConverter")
        )->convertDataToData({}, assembly))}};

    /* Pipeline layout */
    VkPipelineLayout pipelineLayout;
    {
        VkPipelineLayoutCreateInfo info{};
        info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        info.setLayoutCount = 0;
        info.pushConstantRangeCount = 0;
        MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkCreatePipelineLayout(device, &info, nullptr, &pipelineLayout));
    }

    /* Create a graphics pipeline */
    VkPipeline pipeline;
    {
        VkVertexInputBindingDescription binding{};
        binding.binding = 0;
        binding.stride = 2*4*4;

        VkVertexInputAttributeDescription attributes[2]{};
        attributes[0].location = 0; /* position attribute */
        attributes[0].binding = binding.binding;
        attributes[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
        attributes[0].offset = 0;
        attributes[1].location = 1; /* color attribute */
        attributes[1].binding = binding.binding;
        attributes[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
        attributes[1].offset = 4*4;

        VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
        vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
        vertexInputInfo.vertexBindingDescriptionCount = 1;
        vertexInputInfo.pVertexBindingDescriptions = &binding;
        vertexInputInfo.vertexAttributeDescriptionCount = 2;
        vertexInputInfo.pVertexAttributeDescriptions = attributes;

        VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo{};
        inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
        inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

        VkViewport viewport{};
        viewport.width = 800.0f;
        viewport.height = 600.0f;
        viewport.maxDepth = 1.0f;

        VkRect2D scissor{{}, {800, 600}};

        VkPipelineViewportStateCreateInfo viewportInfo{};
        viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
        viewportInfo.viewportCount = 1;
        viewportInfo.pViewports = &viewport;
        viewportInfo.scissorCount = 1;
        viewportInfo.pScissors = &scissor;

        VkPipelineRasterizationStateCreateInfo rasterizationInfo{};
        rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
        rasterizationInfo.lineWidth = 1.0f;
        /* the zero-filled defaults are good enough apparently */

        VkPipelineMultisampleStateCreateInfo multisampleInfo{};
        multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
        multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

        VkPipelineColorBlendAttachmentState blend{};
        blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT|
                               VK_COLOR_COMPONENT_G_BIT|
                               VK_COLOR_COMPONENT_B_BIT|
                               VK_COLOR_COMPONENT_A_BIT;
        VkPipelineColorBlendStateCreateInfo colorBlendInfo{};
        colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
        colorBlendInfo.attachmentCount = 1;
        colorBlendInfo.pAttachments = &blend;

        VkPipelineShaderStageCreateInfo stages[2]{};
        stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
        stages[0].module = shader;
        stages[0].pName = "ver";
        stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
        stages[1].module = shader;
        stages[1].pName = "fra";

        VkGraphicsPipelineCreateInfo info{};
        info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
        info.stageCount = 2;
        info.pStages = stages;
        info.pVertexInputState = &vertexInputInfo;
        info.pInputAssemblyState = &inputAssemblyInfo;
        info.pViewportState = &viewportInfo;
        info.pRasterizationState = &rasterizationInfo;
        info.pMultisampleState = &multisampleInfo;
        info.pColorBlendState = &colorBlendInfo;
        info.layout = pipelineLayout;
        info.renderPass = renderPass;
        info.subpass = 0;
        MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(vkCreateGraphicsPipelines(device, nullptr, 1, &info, nullptr, &pipeline));
    }

    /* Begin recording */
    cmd.begin();

    /* Begin a render pass. Converts the framebuffer attachment from Undefined
       to ColorAttachment layout and clears it. */
    cmd.beginRenderPass(Vk::RenderPassBeginInfo{renderPass, framebuffer}
           .clearColor(0, 0x1f1f1f_srgbf)
       );

    /* Bind the pipeline */
    vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

    /* Bind the vertex buffer */
    {
        const VkDeviceSize offset = 0;
        const VkBuffer handle = buffer;
        vkCmdBindVertexBuffers(cmd, 0, 1, &handle, &offset);
    }

    /* Draw the triangle */
    vkCmdDraw(cmd, 3, 1, 0, 0);

    /* End recording */
    cmd.endRenderPass()
       .end();

    /* Submit the command buffer and wait until done */
    Vk::Fence fence{device};
    queue.submit({Vk::SubmitInfo{}.setCommandBuffers({cmd})}, fence);
    fence.wait();

    /* Read the image back */
    CORRADE_INTERNAL_ASSERT_EXPRESSION(
        PluginManager::Manager<Trade::AbstractImageConverter>{}
            .loadAndInstantiate("AnyImageConverter")
    )->exportToFile(ImageView2D{
        PixelFormat::RGBA8Unorm, {800, 600},
        image.dedicatedMemory().mapRead()}, "image.png");
    Debug{} << "Saved an image to image.png";

    /* Clean up */
    vkDestroyPipeline(device, pipeline, nullptr);
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
}
<|endoftext|>


<commit_before>/*
** SelfPortrait API
** See Copyright Notice in lua_utils.h
*/

#include "test_utils.h"
#include <stdexcept>
#include "str_conversion.h"
#include <cxxtest/TestSuite.h>
//#include <dlfcn.h>
using namespace std;

namespace LuaUtils {

    void addTestFunctionsAndPaths(lua_State* L)
    {
        lua_atpanic(L, atPanicThrow);
        luaL_openlibs(L);
        lua_pushcfunction(L, ts_fail);
        lua_setglobal(L, "TS_FAIL");
        lua_pushcfunction(L, ts_trace);
        lua_setglobal(L, "TS_TRACE");
        lua_pushcfunction(L, ts_warn);
        lua_setglobal(L, "TS_WARN");

        lua_getglobal(L, "package");
        luaL_checktype(L, 1, LUA_TTABLE);

        // for cxxtest.lua
        lua_getfield(L, 1, "path");
        lua_pushstring(L, ";");
        lua_pushstring(L, srcpath().c_str());
        lua_pushstring(L, "/?.lua");
        lua_concat(L, 4);
        lua_setfield(L, 1, "path");

        // for libluacppreflect
        lua_getfield(L, 1, "cpath");
        lua_pushstring(L, ";");
        lua_pushstring(L, binpath().c_str());
        lua_pushstring(L, "/../lua_module/?.so");
        lua_pushstring(L, ";");
        lua_pushstring(L, binpath().c_str());
        lua_pushstring(L, "/../lua_module/?.dll"); // don't want to mess with platform DEFINEs
        lua_concat(L, 7);
        lua_setfield(L, 1, "cpath");

        // Uncomment this to prevent the unloading of the library
        // When the library is unloaded valgrind cannot translate function addresses to names
        // in the stacktrace
        //std::string library_path = fmt_str("%1/../lua_module/libluaselfportrait.so", binpath());
        //void* handle = dlopen(library_path.c_str(), RTLD_NOW);
    }

    int atPanicThrow(lua_State* L) {
        throw std::runtime_error(strconv::fmt_str("Error during execution of Lua code:\n%1", lua_tostring(L, -1)));
        return 0;
    }

    int ts_fail(lua_State* L) {

        const int nargs = lua_gettop(L);

        if (nargs == 3) {
            CxxTest::TestTracker::tracker().failedTest( luaL_checkstring(L, -3), luaL_checkint(L, -2), luaL_checkstring(L, -1) );
        } else if (nargs >= 1) {
            lua_Debug debug;
            lua_getstack(L, 1, &debug);
            lua_getinfo(L, "Sl", &debug);
            CxxTest::TestTracker::tracker().failedTest( debug.short_src, debug.currentline, luaL_checkstring(L, -1) );
        } else {
            luaL_error(L, "TS_FAIL called with an illegal number of arguments");
        }
        return 0;
    }

    int ts_trace(lua_State* L) {

        const int nargs = lua_gettop(L);

        if (nargs == 3) {
            CxxTest::TestTracker::tracker().trace(luaL_checkstring(L, -3), luaL_checkint(L, -2), luaL_checkstring(L, -1) );
        } else if (nargs >= 1) {
            lua_Debug debug;
            lua_getstack(L, 1, &debug);
            lua_getinfo(L, "Sl", &debug);
            CxxTest::TestTracker::tracker().trace( debug.short_src, debug.currentline, luaL_checkstring(L, -1) );
        } else {
            luaL_error(L, "TS_TRACE called with an illegal number of arguments");
        }
        return 0;
    }

    int ts_warn(lua_State* L) {

        const int nargs = lua_gettop(L);

        if (nargs == 3) {
            CxxTest::TestTracker::tracker().warning(luaL_checkstring(L, -3), luaL_checkint(L, -2), luaL_checkstring(L, -1) );
        } else if (nargs >= 1) {
            lua_Debug debug;
            lua_getstack(L, 1, &debug);
            lua_getinfo(L, "Sl", &debug);
            CxxTest::TestTracker::tracker().warning( debug.short_src, debug.currentline, luaL_checkstring(L, -1) );
        } else {
            luaL_error(L, "TS_WARN called with an illegal number of arguments");
        }
        return 0;
    }
}
<commit_msg>Remove duplicate lua_openlibs that resets package.path<commit_after>/*
** SelfPortrait API
** See Copyright Notice in lua_utils.h
*/

#include "test_utils.h"
#include <stdexcept>
#include "str_conversion.h"
#include <cxxtest/TestSuite.h>
//#include <dlfcn.h>
using namespace std;

namespace LuaUtils {

    void addTestFunctionsAndPaths(lua_State* L)
    {
        lua_atpanic(L, atPanicThrow);
        lua_pushcfunction(L, ts_fail);
        lua_setglobal(L, "TS_FAIL");
        lua_pushcfunction(L, ts_trace);
        lua_setglobal(L, "TS_TRACE");
        lua_pushcfunction(L, ts_warn);
        lua_setglobal(L, "TS_WARN");

        lua_getglobal(L, "package");
        luaL_checktype(L, 1, LUA_TTABLE);

        // for cxxtest.lua
        lua_getfield(L, 1, "path");
        lua_pushstring(L, ";");
        lua_pushstring(L, srcpath().c_str());
        lua_pushstring(L, "/?.lua");
        lua_concat(L, 4);
        lua_setfield(L, 1, "path");

        // for libluacppreflect
        lua_getfield(L, 1, "cpath");
        lua_pushstring(L, ";");
        lua_pushstring(L, binpath().c_str());
        lua_pushstring(L, "/../lua_module/?.so");
        lua_pushstring(L, ";");
        lua_pushstring(L, binpath().c_str());
        lua_pushstring(L, "/../lua_module/?.dll"); // don't want to mess with platform DEFINEs
        lua_concat(L, 7);
        lua_setfield(L, 1, "cpath");

        // Uncomment this to prevent the unloading of the library
        // When the library is unloaded valgrind cannot translate function addresses to names
        // in the stacktrace
        //std::string library_path = fmt_str("%1/../lua_module/libluaselfportrait.so", binpath());
        //void* handle = dlopen(library_path.c_str(), RTLD_NOW);
    }

    int atPanicThrow(lua_State* L) {
        throw std::runtime_error(strconv::fmt_str("Error during execution of Lua code:\n%1", lua_tostring(L, -1)));
        return 0;
    }

    int ts_fail(lua_State* L) {

        const int nargs = lua_gettop(L);

        if (nargs == 3) {
            CxxTest::TestTracker::tracker().failedTest( luaL_checkstring(L, -3), luaL_checkint(L, -2), luaL_checkstring(L, -1) );
        } else if (nargs >= 1) {
            lua_Debug debug;
            lua_getstack(L, 1, &debug);
            lua_getinfo(L, "Sl", &debug);
            CxxTest::TestTracker::tracker().failedTest( debug.short_src, debug.currentline, luaL_checkstring(L, -1) );
        } else {
            luaL_error(L, "TS_FAIL called with an illegal number of arguments");
        }
        return 0;
    }

    int ts_trace(lua_State* L) {

        const int nargs = lua_gettop(L);

        if (nargs == 3) {
            CxxTest::TestTracker::tracker().trace(luaL_checkstring(L, -3), luaL_checkint(L, -2), luaL_checkstring(L, -1) );
        } else if (nargs >= 1) {
            lua_Debug debug;
            lua_getstack(L, 1, &debug);
            lua_getinfo(L, "Sl", &debug);
            CxxTest::TestTracker::tracker().trace( debug.short_src, debug.currentline, luaL_checkstring(L, -1) );
        } else {
            luaL_error(L, "TS_TRACE called with an illegal number of arguments");
        }
        return 0;
    }

    int ts_warn(lua_State* L) {

        const int nargs = lua_gettop(L);

        if (nargs == 3) {
            CxxTest::TestTracker::tracker().warning(luaL_checkstring(L, -3), luaL_checkint(L, -2), luaL_checkstring(L, -1) );
        } else if (nargs >= 1) {
            lua_Debug debug;
            lua_getstack(L, 1, &debug);
            lua_getinfo(L, "Sl", &debug);
            CxxTest::TestTracker::tracker().warning( debug.short_src, debug.currentline, luaL_checkstring(L, -1) );
        } else {
            luaL_error(L, "TS_WARN called with an illegal number of arguments");
        }
        return 0;
    }
}
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "errors.hpp"
#include <boost/make_shared.hpp>

#include "buffer_cache/buffer_cache.hpp"
#include "containers/iterators.hpp"
#include "memcached/protocol.hpp"
#include "rdb_protocol/protocol.hpp"
#include "serializer/config.hpp"
#include "serializer/translator.hpp"
#include "unittest/gtest.hpp"
#include "unittest/dummy_namespace_interface.hpp"

namespace unittest {
namespace {

void run_with_namespace_interface(boost::function<void(namespace_interface_t<rdb_protocol_t> *, order_source_t *)> fun) {

    order_source_t order_source;

    /* Pick shards */
    std::vector<rdb_protocol_t::region_t> shards;
    shards.push_back(rdb_protocol_t::region_t(key_range_t(key_range_t::none,   store_key_t(),  key_range_t::open, store_key_t("n"))));
    shards.push_back(rdb_protocol_t::region_t(key_range_t(key_range_t::closed, store_key_t("n"), key_range_t::none, store_key_t() )));

    boost::ptr_vector<mock::temp_file_t> temp_files;
    for (size_t i = 0; i < shards.size(); ++i) {
        temp_files.push_back(new mock::temp_file_t("/tmp/rdb_unittest.XXXXXX"));
    }

    scoped_ptr_t<io_backender_t> io_backender;
    make_io_backender(aio_default, &io_backender);

    scoped_array_t<scoped_ptr_t<serializer_t> > serializers(shards.size());
    for (size_t i = 0; i < shards.size(); ++i) {
        filepath_file_opener_t file_opener(temp_files[i].name(), io_backender.get());
        standard_serializer_t::create(&file_opener,
                                      standard_serializer_t::static_config_t());
        serializers[i].init(new standard_serializer_t(standard_serializer_t::dynamic_config_t(),
                                                      &file_opener,
                                                      &get_global_perfmon_collection()));
    }

    boost::ptr_vector<rdb_protocol_t::store_t> underlying_stores;
    rdb_protocol_t::context_t ctx;

    for (size_t i = 0; i < shards.size(); ++i) {
        underlying_stores.push_back(new rdb_protocol_t::store_t(serializers[i].get(), temp_files[i].name(), GIGABYTE, true, &get_global_perfmon_collection(), &ctx));
    }

    boost::ptr_vector<store_view_t<rdb_protocol_t> > stores;
    for (size_t i = 0; i < shards.size(); ++i) {
        stores.push_back(new store_subview_t<rdb_protocol_t>(&underlying_stores[i], shards[i]));
    }

    /* Set up namespace interface */
    dummy_namespace_interface_t<rdb_protocol_t> nsi(shards, stores.c_array(), &order_source);

    fun(&nsi, &order_source);
}

void run_in_thread_pool_with_namespace_interface(boost::function<void(namespace_interface_t<rdb_protocol_t> *, order_source_t*)> fun) {
    mock::run_in_thread_pool(boost::bind(&run_with_namespace_interface, fun));
}

}   /* anonymous namespace */

/* `SetupTeardown` makes sure that it can start and stop without anything going
horribly wrong */
void run_setup_teardown_test(UNUSED namespace_interface_t<rdb_protocol_t> *nsi, order_source_t *) {
    /* Do nothing */
}
TEST(RDBProtocol, SetupTeardown) {
    run_in_thread_pool_with_namespace_interface(&run_setup_teardown_test);
}

/* `GetSet` tests basic get and set operations */
void run_get_set_test(namespace_interface_t<rdb_protocol_t> *nsi, order_source_t *osource) {
    boost::shared_ptr<scoped_cJSON_t> data(new scoped_cJSON_t(cJSON_CreateNull()));
    {
        rdb_protocol_t::write_t write(rdb_protocol_t::point_write_t(store_key_t("a"), data));
        rdb_protocol_t::write_response_t response;

        cond_t interruptor;
        nsi->write(write, &response, osource->check_in("unittest::run_get_set_test(rdb_protocol.cc-A)"), &interruptor);

        if (rdb_protocol_t::point_write_response_t *maybe_point_write_response_t = boost::get<rdb_protocol_t::point_write_response_t>(&response.response)) {
            EXPECT_EQ(maybe_point_write_response_t->result, STORED);
        } else {
            ADD_FAILURE() << "got wrong type of result back";
        }
    }

    {
        rdb_protocol_t::read_t read(rdb_protocol_t::point_read_t(store_key_t("a")));
        rdb_protocol_t::read_response_t response;

        cond_t interruptor;
        nsi->read(read, &response, osource->check_in("unittest::run_get_set_test(rdb_protocol.cc-B)"), &interruptor);

        if (rdb_protocol_t::point_read_response_t *maybe_point_read_response = boost::get<rdb_protocol_t::point_read_response_t>(&response.response)) {
            EXPECT_TRUE(maybe_point_read_response->data->get() != NULL);
            EXPECT_TRUE(cJSON_Equal(data->get(), maybe_point_read_response->data->get()));
        } else {
            ADD_FAILURE() << "got wrong result back";
        }
    }
}

TEST(RDBProtocol, GetSet) {
    run_in_thread_pool_with_namespace_interface(&run_get_set_test);
}

}   /* namespace unittest */

<commit_msg>Make rdb_protocol unittest work.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "errors.hpp"
#include <boost/make_shared.hpp>

#include "buffer_cache/buffer_cache.hpp"
#include "clustering/administration/metadata.hpp"
#include "containers/iterators.hpp"
#include "memcached/protocol.hpp"
#include "rdb_protocol/protocol.hpp"
#include "rpc/semilattice/semilattice_manager.hpp"
#include "serializer/config.hpp"
#include "serializer/translator.hpp"
#include "unittest/dummy_namespace_interface.hpp"
#include "unittest/gtest.hpp"
#include "rpc/directory/read_manager.hpp"

namespace unittest {
namespace {

void run_with_namespace_interface(boost::function<void(namespace_interface_t<rdb_protocol_t> *, order_source_t *)> fun) {

    order_source_t order_source;

    /* Pick shards */
    std::vector<rdb_protocol_t::region_t> shards;
    shards.push_back(rdb_protocol_t::region_t(key_range_t(key_range_t::none,   store_key_t(),  key_range_t::open, store_key_t("n"))));
    shards.push_back(rdb_protocol_t::region_t(key_range_t(key_range_t::closed, store_key_t("n"), key_range_t::none, store_key_t() )));

    boost::ptr_vector<mock::temp_file_t> temp_files;
    for (size_t i = 0; i < shards.size(); ++i) {
        temp_files.push_back(new mock::temp_file_t("/tmp/rdb_unittest.XXXXXX"));
    }

    scoped_ptr_t<io_backender_t> io_backender;
    make_io_backender(aio_default, &io_backender);

    scoped_array_t<scoped_ptr_t<serializer_t> > serializers(shards.size());
    for (size_t i = 0; i < shards.size(); ++i) {
        filepath_file_opener_t file_opener(temp_files[i].name(), io_backender.get());
        standard_serializer_t::create(&file_opener,
                                      standard_serializer_t::static_config_t());
        serializers[i].init(new standard_serializer_t(standard_serializer_t::dynamic_config_t(),
                                                      &file_opener,
                                                      &get_global_perfmon_collection()));
    }

    boost::ptr_vector<rdb_protocol_t::store_t> underlying_stores;

    /* Create some structures for the rdb_protocol_t::context_t, warning some
     * boilerplate is about to follow, avert your eyes if you have a weak
     * stomach for such things. */
    extproc::spawner_t::info_t spawner_info;
    extproc::spawner_t::create(&spawner_info);
    extproc::pool_group_t pool_group(&spawner_info, extproc::pool_group_t::DEFAULTS);

    int port = mock::randport();
    connectivity_cluster_t c;
    semilattice_manager_t<cluster_semilattice_metadata_t> slm(&c, cluster_semilattice_metadata_t());
    connectivity_cluster_t::run_t cr(&c, mock::get_unittest_addresses(), port, &slm, 0, NULL);

    int port2 = mock::randport();
    connectivity_cluster_t c2;
    directory_read_manager_t<cluster_directory_metadata_t> read_manager(&c2);
    connectivity_cluster_t::run_t cr2(&c2, mock::get_unittest_addresses(), port2, &read_manager, 0, NULL);

    rdb_protocol_t::context_t ctx(&pool_group, NULL, slm.get_root_view(), &read_manager, generate_uuid());

    for (size_t i = 0; i < shards.size(); ++i) {
        underlying_stores.push_back(new rdb_protocol_t::store_t(serializers[i].get(), temp_files[i].name(), GIGABYTE, true, &get_global_perfmon_collection(), &ctx));
    }

    boost::ptr_vector<store_view_t<rdb_protocol_t> > stores;
    for (size_t i = 0; i < shards.size(); ++i) {
        stores.push_back(new store_subview_t<rdb_protocol_t>(&underlying_stores[i], shards[i]));
    }

    /* Set up namespace interface */
    dummy_namespace_interface_t<rdb_protocol_t> nsi(shards, stores.c_array(), &order_source);

    fun(&nsi, &order_source);
}

void run_in_thread_pool_with_namespace_interface(boost::function<void(namespace_interface_t<rdb_protocol_t> *, order_source_t*)> fun) {
    mock::run_in_thread_pool(boost::bind(&run_with_namespace_interface, fun));
}

}   /* anonymous namespace */

/* `SetupTeardown` makes sure that it can start and stop without anything going
horribly wrong */
void run_setup_teardown_test(UNUSED namespace_interface_t<rdb_protocol_t> *nsi, order_source_t *) {
    /* Do nothing */
}
TEST(RDBProtocol, SetupTeardown) {
    run_in_thread_pool_with_namespace_interface(&run_setup_teardown_test);
}

/* `GetSet` tests basic get and set operations */
void run_get_set_test(namespace_interface_t<rdb_protocol_t> *nsi, order_source_t *osource) {
    boost::shared_ptr<scoped_cJSON_t> data(new scoped_cJSON_t(cJSON_CreateNull()));
    {
        rdb_protocol_t::write_t write(rdb_protocol_t::point_write_t(store_key_t("a"), data));
        rdb_protocol_t::write_response_t response;

        cond_t interruptor;
        nsi->write(write, &response, osource->check_in("unittest::run_get_set_test(rdb_protocol.cc-A)"), &interruptor);

        if (rdb_protocol_t::point_write_response_t *maybe_point_write_response_t = boost::get<rdb_protocol_t::point_write_response_t>(&response.response)) {
            EXPECT_EQ(maybe_point_write_response_t->result, STORED);
        } else {
            ADD_FAILURE() << "got wrong type of result back";
        }
    }

    {
        rdb_protocol_t::read_t read(rdb_protocol_t::point_read_t(store_key_t("a")));
        rdb_protocol_t::read_response_t response;

        cond_t interruptor;
        nsi->read(read, &response, osource->check_in("unittest::run_get_set_test(rdb_protocol.cc-B)"), &interruptor);

        if (rdb_protocol_t::point_read_response_t *maybe_point_read_response = boost::get<rdb_protocol_t::point_read_response_t>(&response.response)) {
            EXPECT_TRUE(maybe_point_read_response->data->get() != NULL);
            EXPECT_TRUE(cJSON_Equal(data->get(), maybe_point_read_response->data->get()));
        } else {
            ADD_FAILURE() << "got wrong result back";
        }
    }
}

TEST(RDBProtocol, GetSet) {
    run_in_thread_pool_with_namespace_interface(&run_get_set_test);
}

}   /* namespace unittest */

<|endoftext|>


<commit_before><commit_msg>Removed unused cpp file<commit_after><|endoftext|>