blob: eadc99f7c6114efa36861a019ef554cb770330ef [file] [log] [blame]
#include "event.hpp"
#include <structmember.h>
#include "string_handle.hpp"
#include "extensions/string.hpp"
namespace ittapi
{
template<typename T>
T* event_cast(Event* self);
template<>
PyObject* event_cast(Event* self)
{
return reinterpret_cast<PyObject*>(self);
}
static PyObject* event_new(PyTypeObject* type, PyObject* args, PyObject* kwargs);
static void event_dealloc(PyObject* self);
static PyObject* event_repr(PyObject* self);
static PyObject* event_str(PyObject* self);
static PyObject* event_begin(PyObject* self, PyObject* args);
static PyObject* event_end(PyObject* self, PyObject* args);
static PyMemberDef event_attrs[] =
{
{"name", T_OBJECT_EX, offsetof(Event, name), READONLY, "a name of the event"},
{nullptr},
};
static PyMethodDef event_methods[] =
{
{"begin", event_begin, METH_NOARGS, "Marks the beginning of the event."},
{"end", event_end, METH_NOARGS, "Marks the end of the event."},
{nullptr},
};
PyTypeObject EventType =
{
.ob_base = PyVarObject_HEAD_INIT(nullptr, 0)
.tp_name = "ittapi.native.Event",
.tp_basicsize = sizeof(Event),
.tp_itemsize = 0,
/* Methods to implement standard operations */
.tp_dealloc = event_dealloc,
.tp_vectorcall_offset = 0,
.tp_getattr = nullptr,
.tp_setattr = nullptr,
.tp_as_async = nullptr,
.tp_repr = event_repr,
/* Method suites for standard classes */
.tp_as_number = nullptr,
.tp_as_sequence = nullptr,
.tp_as_mapping = nullptr,
/* More standard operations (here for binary compatibility) */
.tp_hash = nullptr,
.tp_call = nullptr,
.tp_str = event_str,
.tp_getattro = nullptr,
.tp_setattro = nullptr,
/* Functions to access object as input/output buffer */
.tp_as_buffer = nullptr,
/* Flags to define presence of optional/expanded features */
.tp_flags = Py_TPFLAGS_DEFAULT,
/* Documentation string */
.tp_doc = "A class that represents a ITT event.",
/* Assigned meaning in release 2.0 call function for all accessible objects */
.tp_traverse = nullptr,
/* Delete references to contained objects */
.tp_clear = nullptr,
/* Assigned meaning in release 2.1 rich comparisons */
.tp_richcompare = nullptr,
/* weak reference enabler */
.tp_weaklistoffset = 0,
/* Iterators */
.tp_iter = nullptr,
.tp_iternext = nullptr,
/* Attribute descriptor and subclassing stuff */
.tp_methods = event_methods,
.tp_members = event_attrs,
.tp_getset = nullptr,
/* Strong reference on a heap type, borrowed reference on a static type */
.tp_base = nullptr,
.tp_dict = nullptr,
.tp_descr_get = nullptr,
.tp_descr_set = nullptr,
.tp_dictoffset = 0,
.tp_init = nullptr,
.tp_alloc = nullptr,
.tp_new = event_new,
/* Low-level free-memory routine */
.tp_free = nullptr,
/* For PyObject_IS_GC */
.tp_is_gc = nullptr,
.tp_bases = nullptr,
/* method resolution order */
.tp_mro = nullptr,
.tp_cache = nullptr,
.tp_subclasses = nullptr,
.tp_weaklist = nullptr,
.tp_del = nullptr,
/* Type attribute cache version tag. Added in version 2.6 */
.tp_version_tag = 0,
.tp_finalize = nullptr,
.tp_vectorcall = nullptr,
};
static PyObject* event_new(PyTypeObject* type, PyObject* args, PyObject* kwargs)
{
Event* self = event_obj(type->tp_alloc(type, 0));
if (self == nullptr)
{
return nullptr;
}
char name_key[] = { "name" };
char* kwlist[] = { name_key, nullptr };
PyObject* name = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &name))
{
return nullptr;
}
if (name && PyUnicode_Check(name))
{
self->name = pyext::new_ref(name);
}
else if (name && Py_TYPE(name) == &StringHandleType)
{
self->name = pyext::new_ref(string_handle_obj(name)->str);
}
else
{
Py_DecRef(event_cast<PyObject>(self));
PyErr_SetString(PyExc_TypeError, "The passed event name is not a valid instance of str or StringHandle.");
return nullptr;
}
pyext::string name_str = pyext::string::from_unicode(self->name);
if (name_str.c_str() == nullptr)
{
Py_DecRef(event_cast<PyObject>(self));
return nullptr;
}
#if defined(_WIN32)
self->event = __itt_event_createW(name_str.c_str(), static_cast<int>(name_str.length()));
#else
self->event = __itt_event_create(name_str.c_str(), static_cast<int>(name_str.length()));
#endif
return event_cast<PyObject>(self);
}
static void event_dealloc(PyObject* self)
{
Event* obj = event_obj(self);
if (obj == nullptr)
{
return;
}
Py_XDECREF(obj->name);
}
static PyObject* event_repr(PyObject* self)
{
Event* obj = event_check(self);
if (obj == nullptr)
{
return nullptr;
}
return PyUnicode_FromFormat("%s('%U')", EventType.tp_name, obj->name);
}
static PyObject* event_str(PyObject* self)
{
Event* obj = event_check(self);
if (obj == nullptr)
{
return nullptr;
}
if (obj->name == nullptr)
{
PyErr_SetString(PyExc_AttributeError, "The name attribute has not been initialized.");
return nullptr;
}
return pyext::new_ref(obj->name);
}
static PyObject* event_begin(PyObject* self, PyObject* args)
{
Event* obj = event_check(self);
if (obj == nullptr)
{
return nullptr;
}
__itt_event_start(obj->event);
Py_RETURN_NONE;
}
static PyObject* event_end(PyObject* self, PyObject* args)
{
Event* obj = event_check(self);
if (obj == nullptr)
{
return nullptr;
}
__itt_event_end(obj->event);
Py_RETURN_NONE;
}
Event* event_check(PyObject* self)
{
if (self == nullptr || Py_TYPE(self) != &EventType)
{
PyErr_SetString(PyExc_TypeError, "The passed event is not a valid instance of Event type.");
return nullptr;
}
return event_obj(self);
}
int exec_event(PyObject* module)
{
return pyext::add_type(module, &EventType);
}
} // namespace ittapi