object: speed up type verification by not relying on strcmp()

Instead of using string contents for type identification use the address
of a constant string array. This should speed up type verifications a
little sind we only need to compare one machine word instead of a full
string. Also, this saves a few strings.

To make clear that types must be compared via address and not string
contents 'type_name' is now called 'type_id'.

This also simplifies the macros for declaring and defining public and
private subclasses.
This commit is contained in:
Lennart Poettering 2009-08-21 21:27:44 +02:00
parent 5317e35543
commit 9abc010c93
19 changed files with 73 additions and 65 deletions

View file

@ -47,7 +47,7 @@
#include "core.h"
static PA_DEFINE_CHECK_TYPE(pa_core, pa_msgobject);
PA_DEFINE_PUBLIC_CLASS(pa_core, pa_msgobject);
static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_core *c = PA_CORE(o);

View file

@ -165,7 +165,7 @@ struct pa_core {
pa_hook hooks[PA_CORE_HOOK_MAX];
};
PA_DECLARE_CLASS(pa_core);
PA_DECLARE_PUBLIC_CLASS(pa_core);
#define PA_CORE(o) pa_core_cast(o)
enum {

View file

@ -26,22 +26,22 @@
#include "msgobject.h"
PA_DEFINE_CHECK_TYPE(pa_msgobject, pa_object);
PA_DEFINE_PUBLIC_CLASS(pa_msgobject, pa_object);
pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)) {
pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_id, pa_bool_t (*check_type)(const char *type_name)) {
pa_msgobject *o;
pa_assert(size > sizeof(pa_msgobject));
pa_assert(type_name);
pa_assert(type_id);
if (!check_type)
check_type = pa_msgobject_check_type;
pa_assert(check_type(type_name));
pa_assert(check_type("pa_object"));
pa_assert(check_type("pa_msgobject"));
pa_assert(check_type(type_id));
pa_assert(check_type(pa_object_type_id));
pa_assert(check_type(pa_msgobject_type_id));
o = PA_MSGOBJECT(pa_object_new_internal(size, type_name, check_type));
o = PA_MSGOBJECT(pa_object_new_internal(size, type_id, check_type));
o->process_msg = NULL;
return o;
}

View file

@ -38,15 +38,13 @@ struct pa_msgobject {
int (*process_msg)(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
};
pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name));
pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_id, pa_bool_t (*check_type)(const char *type_name));
int pa_msgobject_check_type(const char *type);
#define pa_msgobject_new(type) ((type*) pa_msgobject_new_internal(sizeof(type), #type, type##_check_type))
#define pa_msgobject_new(type) ((type*) pa_msgobject_new_internal(sizeof(type), type##_type_id, type##_check_type))
#define pa_msgobject_free ((void (*) (pa_msgobject* o)) pa_object_free)
#define PA_MSGOBJECT(o) pa_msgobject_cast(o)
PA_DECLARE_CLASS(pa_msgobject);
PA_DECLARE_PUBLIC_CLASS(pa_msgobject);
#endif

View file

@ -28,21 +28,23 @@
#include "object.h"
pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)) {
const char pa_object_type_id[] = "pa_object";
pa_object *pa_object_new_internal(size_t size, const char *type_id, pa_bool_t (*check_type)(const char *type_id)) {
pa_object *o;
pa_assert(size > sizeof(pa_object));
pa_assert(type_name);
pa_assert(type_id);
if (!check_type)
check_type = pa_object_check_type;
pa_assert(check_type(type_name));
pa_assert(check_type("pa_object"));
pa_assert(check_type(type_id));
pa_assert(check_type(pa_object_type_id));
o = pa_xmalloc(size);
PA_REFCNT_INIT(o);
o->type_name = type_name;
o->type_id = type_id;
o->free = pa_object_free;
o->check_type = check_type;
@ -65,8 +67,8 @@ void pa_object_unref(pa_object *o) {
}
}
int pa_object_check_type(const char *type_name) {
pa_assert(type_name);
pa_bool_t pa_object_check_type(const char *type_id) {
pa_assert(type_id);
return pa_streq(type_name, "pa_object");
return type_id == pa_object_type_id;
}

View file

@ -34,21 +34,23 @@ typedef struct pa_object pa_object;
struct pa_object {
PA_REFCNT_DECLARE;
const char *type_name;
const char *type_id;
void (*free)(pa_object *o);
int (*check_type)(const char *type_name);
pa_bool_t (*check_type)(const char *type_name);
};
pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name));
#define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type, type##_check_type)
pa_object *pa_object_new_internal(size_t size, const char *type_id, pa_bool_t (*check_type)(const char *type_id));
#define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), type##_type_id, type##_check_type)
#define pa_object_free ((void (*) (pa_object* _obj)) pa_xfree)
int pa_object_check_type(const char *type);
pa_bool_t pa_object_check_type(const char *type_id);
static inline int pa_object_isinstance(void *o) {
extern const char pa_object_type_id[];
static inline pa_bool_t pa_object_isinstance(void *o) {
pa_object *obj = (pa_object*) o;
return obj ? obj->check_type("pa_object") : 0;
return obj ? obj->check_type(pa_object_type_id) : TRUE;
}
pa_object *pa_object_ref(pa_object *o);
@ -60,7 +62,7 @@ static inline int pa_object_refcnt(pa_object *o) {
static inline pa_object* pa_object_cast(void *o) {
pa_object *obj = (pa_object*) o;
pa_assert(!obj || obj->check_type("pa_object"));
pa_assert(!obj || obj->check_type(pa_object_type_id));
return obj;
}
@ -68,10 +70,10 @@ static inline pa_object* pa_object_cast(void *o) {
#define PA_OBJECT(o) pa_object_cast(o)
#define PA_DECLARE_CLASS(c) \
static inline int c##_isinstance(void *o) { \
#define PA_DECLARE_CLASS_COMMON(c) \
static inline pa_bool_t c##_isinstance(void *o) { \
pa_object *obj = (pa_object*) o; \
return obj ? obj->check_type(#c) : 1; \
return obj ? obj->check_type(c##_type_id) : TRUE; \
} \
static inline c* c##_cast(void *o) { \
pa_assert(c##_isinstance(o)); \
@ -91,12 +93,27 @@ static inline pa_object* pa_object_cast(void *o) {
} \
struct __stupid_useless_struct_to_allow_trailing_semicolon
#define PA_DEFINE_CHECK_TYPE(c, parent) \
int c##_check_type(const char *type) { \
pa_assert(type); \
if (strcmp(type, #c) == 0) \
return 1; \
return parent##_check_type(type); \
#define PA_DECLARE_PUBLIC_CLASS(c) \
extern const char c##_type_id[]; \
PA_DECLARE_CLASS_COMMON(c); \
pa_bool_t c##_check_type(const char *type_id)
#define PA_DEFINE_PUBLIC_CLASS(c, parent) \
const char c##_type_id[] = #c; \
pa_bool_t c##_check_type(const char *type_id) { \
if (type_id == c##_type_id) \
return TRUE; \
return parent##_check_type(type_id); \
} \
struct __stupid_useless_struct_to_allow_trailing_semicolon
#define PA_DEFINE_PRIVATE_CLASS(c, parent) \
static const char c##_type_id[] = #c; \
PA_DECLARE_CLASS_COMMON(c); \
static pa_bool_t c##_check_type(const char *type_id) { \
if (type_id == c##_type_id) \
return TRUE; \
return parent##_check_type(type_id); \
} \
struct __stupid_useless_struct_to_allow_trailing_semicolon

View file

@ -47,9 +47,8 @@ enum {
MEMBLOCKQ_STREAM_MESSAGE_UNLINK,
};
PA_DECLARE_CLASS(memblockq_stream);
PA_DEFINE_PRIVATE_CLASS(memblockq_stream, pa_msgobject);
#define MEMBLOCKQ_STREAM(o) (memblockq_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(memblockq_stream, pa_msgobject);
static void memblockq_stream_unlink(memblockq_stream *u) {
pa_assert(u);

View file

@ -120,9 +120,8 @@ typedef struct connection {
pa_time_event *auth_timeout_event;
} connection;
PA_DECLARE_CLASS(connection);
PA_DEFINE_PRIVATE_CLASS(connection, pa_msgobject);
#define CONNECTION(o) (connection_cast(o))
static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
struct pa_esound_protocol {
PA_REFCNT_DECLARE;

View file

@ -98,17 +98,15 @@ typedef struct record_stream {
pa_usec_t current_source_latency;
} record_stream;
PA_DECLARE_CLASS(record_stream);
#define RECORD_STREAM(o) (record_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(record_stream, pa_msgobject);
PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject);
typedef struct output_stream {
pa_msgobject parent;
} output_stream;
PA_DECLARE_CLASS(output_stream);
#define OUTPUT_STREAM(o) (output_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject);
PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject);
typedef struct playback_stream {
output_stream parent;
@ -138,9 +136,8 @@ typedef struct playback_stream {
uint64_t playing_for, underrun_for;
} playback_stream;
PA_DECLARE_CLASS(playback_stream);
#define PLAYBACK_STREAM(o) (playback_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream);
PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream);
typedef struct upload_stream {
output_stream parent;
@ -156,9 +153,8 @@ typedef struct upload_stream {
pa_proplist *proplist;
} upload_stream;
PA_DECLARE_CLASS(upload_stream);
#define UPLOAD_STREAM(o) (upload_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream);
PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream);
struct pa_native_connection {
pa_msgobject parent;
@ -176,9 +172,8 @@ struct pa_native_connection {
pa_time_event *auth_timeout_event;
};
PA_DECLARE_CLASS(pa_native_connection);
#define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
static PA_DEFINE_CHECK_TYPE(pa_native_connection, pa_msgobject);
PA_DEFINE_PRIVATE_CLASS(pa_native_connection, pa_msgobject);
struct pa_native_protocol {
PA_REFCNT_DECLARE;

View file

@ -69,9 +69,8 @@ typedef struct connection {
} playback;
} connection;
PA_DECLARE_CLASS(connection);
PA_DEFINE_PRIVATE_CLASS(connection, pa_msgobject);
#define CONNECTION(o) (connection_cast(o))
static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
struct pa_simple_protocol {
PA_REFCNT_DECLARE;

View file

@ -44,7 +44,7 @@
#define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
#define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
PA_DEFINE_PUBLIC_CLASS(pa_sink_input, pa_msgobject);
static void sink_input_free(pa_object *o);
static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);

View file

@ -235,7 +235,7 @@ struct pa_sink_input {
void *userdata;
};
PA_DECLARE_CLASS(pa_sink_input);
PA_DECLARE_PUBLIC_CLASS(pa_sink_input);
#define PA_SINK_INPUT(o) pa_sink_input_cast(o)
enum {

View file

@ -52,7 +52,7 @@
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
#define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
PA_DEFINE_PUBLIC_CLASS(pa_sink, pa_msgobject);
static void sink_free(pa_object *s);

View file

@ -191,7 +191,7 @@ struct pa_sink {
void *userdata;
};
PA_DECLARE_CLASS(pa_sink);
PA_DECLARE_PUBLIC_CLASS(pa_sink);
#define PA_SINK(s) (pa_sink_cast(s))
typedef enum pa_sink_message {

View file

@ -64,9 +64,8 @@ enum {
FILE_STREAM_MESSAGE_UNLINK
};
PA_DECLARE_CLASS(file_stream);
PA_DEFINE_PRIVATE_CLASS(file_stream, pa_msgobject);
#define FILE_STREAM(o) (file_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(file_stream, pa_msgobject);
/* Called from main context */
static void file_stream_unlink(file_stream *u) {

View file

@ -41,7 +41,7 @@
#define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
static PA_DEFINE_CHECK_TYPE(pa_source_output, pa_msgobject);
PA_DEFINE_PUBLIC_CLASS(pa_source_output, pa_msgobject);
static void source_output_free(pa_object* mo);

View file

@ -182,7 +182,7 @@ struct pa_source_output {
void *userdata;
};
PA_DECLARE_CLASS(pa_source_output);
PA_DECLARE_PUBLIC_CLASS(pa_source_output);
#define PA_SOURCE_OUTPUT(o) pa_source_output_cast(o)
enum {

View file

@ -46,7 +46,7 @@
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
#define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
PA_DEFINE_PUBLIC_CLASS(pa_source, pa_msgobject);
static void source_free(pa_object *o);

View file

@ -158,7 +158,7 @@ struct pa_source {
void *userdata;
};
PA_DECLARE_CLASS(pa_source);
PA_DECLARE_PUBLIC_CLASS(pa_source);
#define PA_SOURCE(s) pa_source_cast(s)
typedef enum pa_source_message {