PageRenderTime 25ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/KinoSearch/Object/Obj.pm

https://github.com/gitpan/KinoSearch
Perl | 240 lines | 207 code | 31 blank | 2 comment | 7 complexity | 7330d3a9021852e78eed13032e9aef54 MD5 | raw file
  1. package KinoSearch::Object::Obj;
  2. use KinoSearch;
  3. 1;
  4. __END__
  5. __BINDING__
  6. my $xs_code = <<'END_XS_CODE';
  7. MODULE = KinoSearch PACKAGE = KinoSearch::Object::Obj
  8. chy_bool_t
  9. is_a(self, class_name)
  10. kino_Obj *self;
  11. const kino_CharBuf *class_name;
  12. CODE:
  13. {
  14. kino_VTable *target = kino_VTable_fetch_vtable(class_name);
  15. RETVAL = Kino_Obj_Is_A(self, target);
  16. }
  17. OUTPUT: RETVAL
  18. void
  19. STORABLE_freeze(self, ...)
  20. kino_Obj *self;
  21. PPCODE:
  22. {
  23. CHY_UNUSED_VAR(self);
  24. if (items < 2 || !SvTRUE(ST(1))) {
  25. SV *retval;
  26. kino_ByteBuf *serialized_bb;
  27. kino_RAMFileHandle *file_handle = kino_RAMFH_open(NULL,
  28. KINO_FH_WRITE_ONLY | KINO_FH_CREATE, NULL);
  29. kino_OutStream *target = kino_OutStream_open((kino_Obj*)file_handle);
  30. Kino_Obj_Serialize(self, target);
  31. Kino_OutStream_Close(target);
  32. serialized_bb = Kino_RAMFile_Get_Contents(
  33. Kino_RAMFH_Get_File(file_handle));
  34. retval = XSBind_bb_to_sv(serialized_bb);
  35. KINO_DECREF(file_handle);
  36. KINO_DECREF(target);
  37. if (SvCUR(retval) == 0) { // Thwart Storable bug
  38. THROW(KINO_ERR, "Calling serialize produced an empty string");
  39. }
  40. ST(0) = sv_2mortal(retval);
  41. XSRETURN(1);
  42. }
  43. }
  44. =begin comment
  45. Calls deserialize(), and copies the object pointer. Since deserialize is an
  46. abstract method, it will confess() unless implemented.
  47. =end comment
  48. =cut
  49. void
  50. STORABLE_thaw(blank_obj, cloning, serialized_sv)
  51. SV *blank_obj;
  52. SV *cloning;
  53. SV *serialized_sv;
  54. PPCODE:
  55. {
  56. char *class_name = HvNAME(SvSTASH(SvRV(blank_obj)));
  57. kino_ZombieCharBuf *klass
  58. = CFISH_ZCB_WRAP_STR(class_name, strlen(class_name));
  59. kino_VTable *vtable = (kino_VTable*)kino_VTable_singleton(
  60. (kino_CharBuf*)klass, NULL);
  61. STRLEN len;
  62. char *ptr = SvPV(serialized_sv, len);
  63. kino_ViewByteBuf *contents = kino_ViewBB_new(ptr, len);
  64. kino_RAMFile *ram_file = kino_RAMFile_new((kino_ByteBuf*)contents, true);
  65. kino_RAMFileHandle *file_handle
  66. = kino_RAMFH_open(NULL, KINO_FH_READ_ONLY, ram_file);
  67. kino_InStream *instream = kino_InStream_open((kino_Obj*)file_handle);
  68. kino_Obj *self = Kino_VTable_Foster_Obj(vtable, blank_obj);
  69. kino_Obj *deserialized = Kino_Obj_Deserialize(self, instream);
  70. CHY_UNUSED_VAR(cloning);
  71. KINO_DECREF(contents);
  72. KINO_DECREF(ram_file);
  73. KINO_DECREF(file_handle);
  74. KINO_DECREF(instream);
  75. // Catch bad deserialize() override.
  76. if (deserialized != self) {
  77. THROW(KINO_ERR, "Error when deserializing obj of class %o", klass);
  78. }
  79. }
  80. void
  81. DESTROY(self)
  82. kino_Obj *self;
  83. PPCODE:
  84. /*
  85. {
  86. char *perl_class = HvNAME(SvSTASH(SvRV(ST(0))));
  87. warn("Destroying: 0x%x %s", (unsigned)self, perl_class);
  88. }
  89. */
  90. Kino_Obj_Destroy(self);
  91. END_XS_CODE
  92. my $synopsis = <<'END_SYNOPSIS';
  93. package MyObj;
  94. use base qw( KinoSearch::Object::Obj );
  95. # Inside-out member var.
  96. my %foo;
  97. sub new {
  98. my ( $class, %args ) = @_;
  99. my $foo = delete $args{foo};
  100. my $self = $class->SUPER::new(%args);
  101. $foo{$$self} = $foo;
  102. return $self;
  103. }
  104. sub get_foo {
  105. my $self = shift;
  106. return $foo{$$self};
  107. }
  108. sub DESTROY {
  109. my $self = shift;
  110. delete $foo{$$self};
  111. $self->SUPER::DESTROY;
  112. }
  113. END_SYNOPSIS
  114. my $description = <<'END_DESCRIPTION';
  115. All objects in the KinoSearch:: hierarchy descend from
  116. KinoSearch::Object::Obj. All classes are implemented as blessed scalar
  117. references, with the scalar storing a pointer to a C struct.
  118. ==head2 Subclassing
  119. The recommended way to subclass KinoSearch::Object::Obj and its descendants is
  120. to use the inside-out design pattern. (See L<Class::InsideOut> for an
  121. introduction to inside-out techniques.)
  122. Since the blessed scalar stores a C pointer value which is unique per-object,
  123. C<$$self> can be used as an inside-out ID.
  124. # Accessor for 'foo' member variable.
  125. sub get_foo {
  126. my $self = shift;
  127. return $foo{$$self};
  128. }
  129. Caveats:
  130. ==over
  131. ==item *
  132. Inside-out aficionados will have noted that the "cached scalar id" stratagem
  133. recommended above isn't compatible with ithreads -- but KinoSearch doesn't
  134. support ithreads anyway, so it doesn't matter.
  135. ==item *
  136. Overridden methods must not return undef unless the API specifies that
  137. returning undef is permissible. (Failure to adhere to this rule currently
  138. results in a segfault rather than an exception.)
  139. ==back
  140. ==head1 CONSTRUCTOR
  141. ==head2 new()
  142. Abstract constructor -- must be invoked via a subclass. Attempting to
  143. instantiate objects of class "KinoSearch::Object::Obj" directly causes an
  144. error.
  145. Takes no arguments; if any are supplied, an error will be reported.
  146. ==head1 DESTRUCTOR
  147. ==head2 DESTROY
  148. All KinoSearch classes implement a DESTROY method; if you override it in a
  149. subclass, you must call C<< $self->SUPER::DESTROY >> to avoid leaking memory.
  150. END_DESCRIPTION
  151. Clownfish::Binding::Perl::Class->register(
  152. parcel => "KinoSearch",
  153. class_name => "KinoSearch::Object::Obj",
  154. xs_code => $xs_code,
  155. bind_methods => [
  156. qw(
  157. Get_RefCount
  158. Inc_RefCount
  159. Dec_RefCount
  160. Get_VTable
  161. To_String
  162. To_I64
  163. To_F64
  164. Dump
  165. _load|Load
  166. Clone
  167. Mimic
  168. Equals
  169. Hash_Sum
  170. Serialize
  171. Deserialize
  172. Destroy
  173. )
  174. ],
  175. bind_constructors => ["new"],
  176. make_pod => {
  177. synopsis => $synopsis,
  178. description => $description,
  179. methods => [
  180. qw(
  181. to_string
  182. to_i64
  183. to_f64
  184. equals
  185. dump
  186. load
  187. )
  188. ],
  189. }
  190. );
  191. __COPYRIGHT__
  192. Copyright 2005-2011 Marvin Humphrey
  193. This program is free software; you can redistribute it and/or modify
  194. under the same terms as Perl itself.