// SCE CONFIDENTIAL
// PLAYSTATION(R)3 Programmer Tool Runtime Library 250.001
// Copyright (C) 2008 Sony Computer Entertainment Inc.
// All Rights Reserved.

#ifndef __CELL_UTIL_SPURS_H__
#define __CELL_UTIL_SPURS_H__ 1

#include <cellUtilSpursDefine.h>
#include <cell/spurs.h>

#include <cstring>						// std::strlen (missing strnlen)

__CELL_UTIL_SPURS_BEGIN

class Spurs : public CellSpurs {
	Spurs(const Spurs&);
	Spurs& operator =(const Spurs&);

public:
	static const uint32_t DEFAULT_NUM_SPUS = 5;
	static const uint32_t DEFAULT_PPU_THREAD_PRIORITY = 1000;
	static const uint32_t DEFAULT_SPU_THREAD_GROUP_PRIORITY = 250;
	static const uint32_t ALIGN = CELL_SPURS_ALIGN;

	enum Type {
		TYPE_EXCLUSIVE_NON_CONTEXT = 0,
		TYPE_SHARED_WITH_ANY = 1,
		TYPE_SHARED_WITH_HIGHER = 2
	};

	Spurs() {}

	static int initialize(Spurs* spurs,
						  const char *prefix,
						  uint32_t nSpus = DEFAULT_NUM_SPUS,
						  int spuPriority = DEFAULT_SPU_THREAD_GROUP_PRIORITY,
						  int ppuPriority = DEFAULT_PPU_THREAD_PRIORITY,
						  Type type = TYPE_EXCLUSIVE_NON_CONTEXT)
		{
			CellSpursAttribute attr;
			bool exitIfNoWork = (type == TYPE_SHARED_WITH_ANY);
			__RETURN_IF(cellSpursAttributeInitialize(&attr, nSpus, spuPriority, ppuPriority, exitIfNoWork));
			__RETURN_IF(cellSpursAttributeEnableSpuPrintfIfAvailable(&attr));
			__RETURN_IF(cellSpursAttributeSetNamePrefix(&attr, prefix, std::strlen(prefix)));
			int _type = (type == TYPE_EXCLUSIVE_NON_CONTEXT)
				? SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT
				: SYS_SPU_THREAD_GROUP_TYPE_NORMAL;
			__RETURN_IF(cellSpursAttributeSetSpuThreadGroupType(&attr,_type));
			return cellSpursInitializeWithAttribute(spurs, &attr);
		}

	static int initialize(Spurs* spurs,
						  const char *prefix,
						  uint32_t nSpus,
						  int spuPriority,
						  int ppuPriority,
						  bool exitIfNoWork,
						  sys_memory_container_t container)
		{
			CellSpursAttribute attr;
			__RETURN_IF(cellSpursAttributeInitialize(&attr, nSpus, spuPriority, ppuPriority, exitIfNoWork));
			__RETURN_IF(cellSpursAttributeEnableSpuPrintfIfAvailable(&attr));
			__RETURN_IF(cellSpursAttributeSetMemoryContainerForSpuThread(&attr, container));
			__RETURN_IF(cellSpursAttributeSetNamePrefix(&attr, prefix, std::strlen(prefix)));
			return cellSpursInitializeWithAttribute(spurs, &attr);
		}

	int finalize()
		{
			return cellSpursFinalize(this);
		}

	int enableExceptionEventHandler()
		{
			return cellSpursEnableExceptionEventHandler(this, true);
		}
	int disableExceptionEventHandler()
		{
			return cellSpursEnableExceptionEventHandler(this, false);
		}
	//
	// Information
	//
	int getSpuThreadGroupId(sys_spu_thread_group_t* group)
		{
			return cellSpursGetSpuThreadGroupId(this, group);
		}
	int getNumSpuThread(uint32_t* nThreads)
		{
			return cellSpursGetNumSpuThread(this, nThreads);
		}
	int getSpuThreadId(sys_spu_thread_t* thread, uint32_t* nThreads)
		{
			return cellSpursGetSpuThreadId(this, thread, nThreads);
		}
	int getInfo(CellSpursInfo *info)
		{
			return cellSpursGetInfo(this, info);
		}
	//
	// workload
	//
	int setMaxContention(CellSpursWorkloadId id, uint32_t maxContention)
		{
			return cellSpursSetMaxContention(this, id, maxContention);
		}
	int setPriorities(CellSpursWorkloadId id, const uint8_t priorities[CELL_SPURS_MAX_SPU])
		{
			return cellSpursSetPriorities(this, id, priorities);
		}
} __attribute__((aligned(CELL_SPURS_ALIGN)));

__CELL_UTIL_SPURS_END

#endif // __CELL_UTIL_SPURS_H__

// Local Variables:
// mode: C++
// c-file-style: "stroustrup"
// tab-width: 4
// End:
// vim:sw=4:sts=4:ts=4
