Find file
Fetching contributors…
Cannot retrieve contributors at this time
197 lines (142 sloc) 5.09 KB
/*
Copyright (C) 2011-2014, Parrot Foundation.
=head1 NAME
src/pmc/proxy.pmc - Proxy PMC
=head1 DESCRIPTION
Proxy objects are generated automatically and are used to protect objects from
being written to directly by other threads.
All methods which are not defined here get a default implementation
generated from F<src/vtable.tbl> by F<tools/build/pmc2c.pl>.
=head2 Functions
=over 4
=cut
*/
#include "parrot/parrot.h"
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
static STRING * caller(PARROT_INTERP, ARGIN_NULLOK(PMC *pmc))
__attribute__nonnull__(1);
PARROT_DOES_NOT_RETURN
static void cant_do_write_method(PARROT_INTERP,
ARGIN_NULLOK(PMC *pmc),
int index)
__attribute__nonnull__(1);
#define ASSERT_ARGS_caller __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_cant_do_write_method __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
/*
=item C<static STRING * caller(PARROT_INTERP, PMC *pmc)>
Returns a C string for the name of C<*pmc>.
=cut
*/
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
static STRING *
caller(PARROT_INTERP, ARGIN_NULLOK(PMC *pmc))
{
ASSERT_ARGS(caller)
return !PMC_IS_NULL(pmc) && pmc->vtable && pmc->vtable->whoami
? VTABLE_name(interp, pmc)
: CONST_STRING(interp, "(null)");
}
/*
=item C<static void cant_do_write_method(PARROT_INTERP, PMC *pmc, int index)>
Throws an exception "$methname() on read-only instance of '$class'", used by
all updating messages on read-only instances.
=cut
*/
PARROT_DOES_NOT_RETURN
static void
cant_do_write_method(PARROT_INTERP, ARGIN_NULLOK(PMC *pmc), int index)
{
ASSERT_ARGS(cant_do_write_method)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_WRITE_TO_CONSTCLASS,
"%s() in read-only proxy of '%Ss'",
Parrot_get_vtable_name(interp, index),
caller(interp, pmc));
}
pmclass Proxy auto_attrs {
ATTR PMC *target; /* The PMC we proxy to */
ATTR Parrot_Interp interp; /* The interpreter owning target */
VTABLE void init() {
Parrot_Proxy_attributes * const core_struct = PARROT_PROXY(SELF);
/* Set flags for custom GC mark. */
PObj_custom_mark_SET(SELF);
core_struct->target = PMCNULL;
core_struct->interp = INTERP;
}
VTABLE void init_pmc(PMC *target) {
Parrot_Proxy_attributes * const core_struct = PARROT_PROXY(SELF);
/* Set flags for custom GC mark. */
PObj_custom_mark_SET(SELF);
PARROT_ASSERT(!PMC_IS_NULL(target));
PARROT_ASSERT(target->vtable->base_type != enum_class_Proxy);
core_struct->target = target;
core_struct->interp = INTERP;
}
/*
=item C<void mark()>
Don't mark target and interp since they belong to a different interpreter.
=cut
*/
VTABLE void mark() :no_wb {
UNUSED(INTERP)
UNUSED(SELF)
}
VTABLE PMC *find_method(STRING *method_name) :no_wb {
UNUSED(INTERP)
return VTABLE_find_method(PARROT_PROXY(SELF)->interp, PARROT_PROXY(SELF)->target,
method_name);
}
VTABLE void *get_pointer_keyed_str(STRING *key) :no_wb {
Parrot_Proxy_attributes * const data = PARROT_PROXY(SELF);
void * result;
PARROT_ASSERT(interp != data->interp);
/* block the GC to prevent it from finding foreign PMCs on the stack */
Parrot_block_GC_mark(interp);
Interp_flags_SET(interp, PARROT_THR_FLAG_NEW_PMC);
result = VTABLE_get_pointer_keyed_str(interp, data->target, key);
Interp_flags_CLEAR(interp, PARROT_THR_FLAG_NEW_PMC);
/* workaround for TT #1219, see Parrot_ns_find_namespace_global */
if (data->target->vtable->base_type == enum_class_NameSpace) {
if (! PMC_IS_NULL((PMC *) result)) {
if (PObj_is_new_TEST((PMC*)result)) {
#ifdef THREAD_DEBUG
PARROT_ASSERT(((PMC *)result)->orig_interp == interp);
#endif
abort();
PObj_is_new_CLEAR((PMC*)result);
}
else {
#ifdef THREAD_DEBUG
PARROT_ASSERT(((PMC *)result)->orig_interp != interp);
#endif
result = Parrot_thread_create_proxy(data->interp, interp, (PMC*)result);
}
}
}
Parrot_unblock_GC_mark(interp);
return result;
}
VTABLE PMC *instantiate(PMC *init) :no_wb {
PMC * const _class = PARROT_PROXY(SELF)->target;
/*TODO will fail if the class has not been instantiated in the main thread before */
PARROT_ASSERT(_class->vtable->base_type != enum_class_Proxy);
return VTABLE_instantiate(interp, _class, init);
}
}
/*
=back
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/