indexing description: "[ This network object wrapps one or multiple EM_NET_EVENT_OBJECT such that they can be transmitted over a network in one message. This wrapper manages a queue of incomming and outgoing events. All features are available trough EM_NET_BASE, it is not necessary to manually deal with it. ]" date: "$Date$" revision: "$Revision$" class EM_NET_EVENT_CONTAINER_OBJECT inherit EM_NET_OBJECT redefine is_synchronisation_needed, make_set_type end EM_TIME_SINGLETON export {NONE} all end create {EM_NET_OBJECT_TYPES} make_set_type feature -- Initialisation make_set_type (a_type_id: INTEGER) is -- Initalize a new wrapper for EM_NET_EVENT_OBJECTs. do Precursor {EM_NET_OBJECT} (a_type_id) create outgoing_net_events.make create incoming_net_events.make end feature -- Event handling publish (an_event: EM_NET_EVENT_OBJECT) is -- Publish `an_event' to the clients that belong to `group'. require an_object_not_void : an_event /= Void do outgoing_net_events.put_first (an_event) ensure outgoing_net_events.has (an_event) end feature -- Serialization serialize (a_serializer: EM_NET_SERIALIZER) is -- Serialize to the given stream using `a_serializer'. local i: INTEGER do from i := event_count_to_serialize a_serializer.put_integer (i) until i = 0 loop a_serializer.put_integer (outgoing_net_events.first.type_id) outgoing_net_events.first.serialize (a_serializer) outgoing_net_events.remove_first i := i - 1 end end serialization_byte_count: INTEGER is -- Count of bytes needed for a successful serialization -- This may be a constant or a dynamic value. require else serialization_needed: is_synchronisation_needed local cursor: DS_LINKED_LIST_CURSOR[EM_NET_OBJECT] byte_count: INTEGER old_byte_count: INTEGER do byte_count := 4 create cursor.make(outgoing_net_events) from cursor.start until cursor.after or else byte_count > max_serialization_byte_count loop old_byte_count := byte_count byte_count := byte_count + 4 byte_count := byte_count + cursor.item.serialization_byte_count cursor.forth end if byte_count > max_serialization_byte_count then byte_count := old_byte_count debug("em_mp") io.put_string("really heavy event load!!%N") end end Result := byte_count end event_count_to_serialize: INTEGER is -- Count of event objects we can serialize without breaking the max_serialization_byte_count limit. local cursor : DS_LINKED_LIST_CURSOR[EM_NET_OBJECT] items: INTEGER byte_count: INTEGER old_byte_count: INTEGER do byte_count := 4 create cursor.make (outgoing_net_events) from cursor.start until cursor.after or else byte_count > max_serialization_byte_count loop old_byte_count := byte_count byte_count := byte_count + 4 byte_count := byte_count + cursor.item.serialization_byte_count items := items + 1 cursor.forth end if byte_count > max_serialization_byte_count then items := items - 1 end Result := items ensure at_least_one_event_to_serialize: Result > 0 end unserialize(an_unserializer : EM_NET_UNSERIALIZER) is -- Unserialize from a given stream using `an_unserializer'. local count: INTEGER a_type_id: INTEGER an_object: EM_NET_EVENT_OBJECT a_2pc_event: EM_NET_2PC_EVENT_OBJECT do an_unserializer.read_integer count := an_unserializer.last_integer from until count <= 0 loop an_unserializer.read_integer a_type_id := an_unserializer.last_integer check object_type_exists: net_object_factory.has_object_type (a_type_id) end an_object ?= net_object_factory.create_object_by_type_id (a_type_id) check an_object_not_void: an_object /= Void end an_object.set_group(updating_connection.personal_group) an_object.set_updating_connection (updating_connection) an_object.make_from_stream (an_unserializer) a_2pc_event ?= an_object if a_2pc_event /= Void then debug ("em_mp") io.put_string ("Received a 2PC event.%N") end if not a_2pc_event.group.acknowledged_event.has (a_2pc_event.id) then debug ("em_mp") io.put_string ("Processing event.%N") end incoming_net_events.put_first (an_object) a_2pc_event.group.acknowledged_event.force (time.ticks, a_2pc_event.id) else debug ("em_mp") io.put_string ("Event skipped, because it's been received earlier.%N") end end else incoming_net_events.put_first (an_object) end count := count - 1 end end feature -- Element change wipe_out is -- Wipe out the list of incoming objects. -- Most probably you just processed them all and you don't need them anymore. do incoming_net_events.wipe_out end set_net_object_factory (an_object_factory: EM_NET_OBJECT_FACTORY) is -- Set the factory that is used to create objects and events. require factory_not_void: an_object_factory /= Void do net_object_factory := an_object_factory ensure factory_set: net_object_factory = an_object_factory end feature -- Information is_synchronisation_needed : BOOLEAN is -- Is synchronisation needed? do Result:= not outgoing_net_events.is_empty end feature {EM_NET_BASE} -- Implementation outgoing_net_events: DS_LINKED_LIST[EM_NET_EVENT_OBJECT] incoming_net_events: DS_LINKED_LIST[EM_NET_EVENT_OBJECT] net_object_factory: EM_NET_OBJECT_FACTORY -- Object factory that is used to create objects and events end