diff options
author | unknown | 2010-05-12 15:59:48 -0700 |
---|---|---|
committer | unknown | 2010-05-12 15:59:48 -0700 |
commit | bf5c81d77e492cd6df5517ecab32cd64168b01c2 (patch) | |
tree | ecbbfded19609dc8bcd39c0a8adea705c192fdb3 /OpenSim/Framework | |
parent | Removed the unreferenced MaxPrimsPerFrame from OpenSim.ini.example (diff) | |
download | opensim-SC_OLD-bf5c81d77e492cd6df5517ecab32cd64168b01c2.zip opensim-SC_OLD-bf5c81d77e492cd6df5517ecab32cd64168b01c2.tar.gz opensim-SC_OLD-bf5c81d77e492cd6df5517ecab32cd64168b01c2.tar.bz2 opensim-SC_OLD-bf5c81d77e492cd6df5517ecab32cd64168b01c2.tar.xz |
* Initial commit of the slimupdates2 rewrite. This pass maintains the original behavior of avatar update sending and has a simplified set of IClientAPI methods for sending avatar/prim updates
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r-- | OpenSim/Framework/IClientAPI.cs | 258 | ||||
-rw-r--r-- | OpenSim/Framework/ISceneEntity.cs | 37 | ||||
-rw-r--r-- | OpenSim/Framework/Lazy.cs | 236 |
3 files changed, 314 insertions, 217 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 01daeb1..00681cf 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -571,207 +571,6 @@ namespace OpenSim.Framework | |||
571 | public float dwell; | 571 | public float dwell; |
572 | } | 572 | } |
573 | 573 | ||
574 | public struct SendAvatarData | ||
575 | { | ||
576 | public readonly ulong RegionHandle; | ||
577 | public readonly string FirstName; | ||
578 | public readonly string LastName; | ||
579 | public readonly string GroupTitle; | ||
580 | public readonly UUID AvatarID; | ||
581 | public readonly uint AvatarLocalID; | ||
582 | public readonly Vector3 Position; | ||
583 | public readonly byte[] TextureEntry; | ||
584 | public readonly uint ParentID; | ||
585 | public readonly Quaternion Rotation; | ||
586 | |||
587 | public SendAvatarData(ulong regionHandle, string firstName, string lastName, string groupTitle, UUID avatarID, | ||
588 | uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation) | ||
589 | { | ||
590 | RegionHandle = regionHandle; | ||
591 | FirstName = firstName; | ||
592 | LastName = lastName; | ||
593 | GroupTitle = groupTitle; | ||
594 | AvatarID = avatarID; | ||
595 | AvatarLocalID = avatarLocalID; | ||
596 | Position = position; | ||
597 | TextureEntry = textureEntry; | ||
598 | ParentID = parentID; | ||
599 | Rotation = rotation; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | public struct SendAvatarTerseData | ||
604 | { | ||
605 | public readonly ulong RegionHandle; | ||
606 | public readonly ushort TimeDilation; | ||
607 | public readonly uint LocalID; | ||
608 | public readonly Vector3 Position; | ||
609 | public readonly Vector3 Velocity; | ||
610 | public readonly Vector3 Acceleration; | ||
611 | public readonly Quaternion Rotation; | ||
612 | public readonly Vector4 CollisionPlane; | ||
613 | public readonly UUID AgentID; | ||
614 | public readonly byte[] TextureEntry; | ||
615 | public readonly double Priority; | ||
616 | |||
617 | public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, | ||
618 | Vector3 acceleration, Quaternion rotation, Vector4 collisionPlane, UUID agentid, byte[] textureEntry, double priority) | ||
619 | { | ||
620 | RegionHandle = regionHandle; | ||
621 | TimeDilation = timeDilation; | ||
622 | LocalID = localID; | ||
623 | Position = position; | ||
624 | Velocity = velocity; | ||
625 | Acceleration = acceleration; | ||
626 | Rotation = rotation; | ||
627 | CollisionPlane = collisionPlane; | ||
628 | AgentID = agentid; | ||
629 | TextureEntry = textureEntry; | ||
630 | Priority = priority; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | public struct SendPrimitiveTerseData | ||
635 | { | ||
636 | public readonly ulong RegionHandle; | ||
637 | public readonly ushort TimeDilation; | ||
638 | public readonly uint LocalID; | ||
639 | public readonly Vector3 Position; | ||
640 | public readonly Quaternion Rotation; | ||
641 | public readonly Vector3 Velocity; | ||
642 | public readonly Vector3 Acceleration; | ||
643 | public readonly Vector3 AngularVelocity; | ||
644 | public readonly UUID AssetID; | ||
645 | public readonly UUID OwnerID; | ||
646 | public readonly int AttachPoint; | ||
647 | public readonly byte[] TextureEntry; | ||
648 | public readonly double Priority; | ||
649 | |||
650 | public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, | ||
651 | Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 rotationalvelocity, | ||
652 | UUID assetID, UUID ownerID, int attachPoint, byte[] textureEntry, double priority) | ||
653 | { | ||
654 | RegionHandle = regionHandle; | ||
655 | TimeDilation = timeDilation; | ||
656 | LocalID = localID; | ||
657 | Position = position; | ||
658 | Rotation = rotation; | ||
659 | Velocity = velocity; | ||
660 | Acceleration = acceleration; | ||
661 | AngularVelocity = rotationalvelocity; | ||
662 | AssetID = assetID; | ||
663 | OwnerID = ownerID; | ||
664 | AttachPoint = attachPoint; | ||
665 | TextureEntry = textureEntry; | ||
666 | Priority = priority; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | public struct SendPrimitiveData | ||
671 | { | ||
672 | private ulong m_regionHandle; | ||
673 | private ushort m_timeDilation; | ||
674 | private uint m_localID; | ||
675 | private PrimitiveBaseShape m_primShape; | ||
676 | private Vector3 m_pos; | ||
677 | private Vector3 m_vel; | ||
678 | private Vector3 m_acc; | ||
679 | private Quaternion m_rotation; | ||
680 | private Vector3 m_rvel; | ||
681 | private PrimFlags m_flags; | ||
682 | private UUID m_objectID; | ||
683 | private UUID m_ownerID; | ||
684 | private string m_text; | ||
685 | private byte[] m_color; | ||
686 | private uint m_parentID; | ||
687 | private byte[] m_particleSystem; | ||
688 | private byte m_clickAction; | ||
689 | private byte m_material; | ||
690 | private byte[] m_textureanim; | ||
691 | private bool m_attachment; | ||
692 | private uint m_AttachPoint; | ||
693 | private UUID m_AssetId; | ||
694 | private UUID m_SoundId; | ||
695 | private double m_SoundVolume; | ||
696 | private byte m_SoundFlags; | ||
697 | private double m_SoundRadius; | ||
698 | private double m_priority; | ||
699 | |||
700 | public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, | ||
701 | Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, | ||
702 | uint flags, UUID objectID, UUID ownerID, string text, byte[] color, | ||
703 | uint parentID, byte[] particleSystem, byte clickAction, byte material, double priority) : | ||
704 | this(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID, | ||
705 | ownerID, text, color, parentID, particleSystem, clickAction, material, new byte[0], false, 0, UUID.Zero, | ||
706 | UUID.Zero, 0, 0, 0, priority) { } | ||
707 | |||
708 | public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, | ||
709 | Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, | ||
710 | uint flags, | ||
711 | UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, | ||
712 | byte[] particleSystem, | ||
713 | byte clickAction, byte material, byte[] textureanim, bool attachment, | ||
714 | uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, | ||
715 | double SoundRadius, double priority) | ||
716 | { | ||
717 | this.m_regionHandle = regionHandle; | ||
718 | this.m_timeDilation = timeDilation; | ||
719 | this.m_localID = localID; | ||
720 | this.m_primShape = primShape; | ||
721 | this.m_pos = pos; | ||
722 | this.m_vel = vel; | ||
723 | this.m_acc = acc; | ||
724 | this.m_rotation = rotation; | ||
725 | this.m_rvel = rvel; | ||
726 | this.m_flags = (PrimFlags)flags; | ||
727 | this.m_objectID = objectID; | ||
728 | this.m_ownerID = ownerID; | ||
729 | this.m_text = text; | ||
730 | this.m_color = color; | ||
731 | this.m_parentID = parentID; | ||
732 | this.m_particleSystem = particleSystem; | ||
733 | this.m_clickAction = clickAction; | ||
734 | this.m_material = material; | ||
735 | this.m_textureanim = textureanim; | ||
736 | this.m_attachment = attachment; | ||
737 | this.m_AttachPoint = AttachPoint; | ||
738 | this.m_AssetId = AssetId; | ||
739 | this.m_SoundId = SoundId; | ||
740 | this.m_SoundVolume = SoundVolume; | ||
741 | this.m_SoundFlags = SoundFlags; | ||
742 | this.m_SoundRadius = SoundRadius; | ||
743 | this.m_priority = priority; | ||
744 | } | ||
745 | |||
746 | public ulong regionHandle { get { return this.m_regionHandle; } } | ||
747 | public ushort timeDilation { get { return this.m_timeDilation; } } | ||
748 | public uint localID { get { return this.m_localID; } } | ||
749 | public PrimitiveBaseShape primShape { get { return this.m_primShape; } } | ||
750 | public Vector3 pos { get { return this.m_pos; } } | ||
751 | public Vector3 vel { get { return this.m_vel; } } | ||
752 | public Vector3 acc { get { return this.m_acc; } } | ||
753 | public Quaternion rotation { get { return this.m_rotation; } } | ||
754 | public Vector3 rvel { get { return this.m_rvel; } } | ||
755 | public PrimFlags flags { get { return this.m_flags; } } | ||
756 | public UUID objectID { get { return this.m_objectID; } } | ||
757 | public UUID ownerID { get { return this.m_ownerID; } } | ||
758 | public string text { get { return this.m_text; } } | ||
759 | public byte[] color { get { return this.m_color; } } | ||
760 | public uint parentID { get { return this.m_parentID; } } | ||
761 | public byte[] particleSystem { get { return this.m_particleSystem; } } | ||
762 | public byte clickAction { get { return this.m_clickAction; } } | ||
763 | public byte material { get { return this.m_material; } } | ||
764 | public byte[] textureanim { get { return this.m_textureanim; } } | ||
765 | public bool attachment { get { return this.m_attachment; } } | ||
766 | public uint AttachPoint { get { return this.m_AttachPoint; } } | ||
767 | public UUID AssetId { get { return this.m_AssetId; } } | ||
768 | public UUID SoundId { get { return this.m_SoundId; } } | ||
769 | public double SoundVolume { get { return this.m_SoundVolume; } } | ||
770 | public byte SoundFlags { get { return this.m_SoundFlags; } } | ||
771 | public double SoundRadius { get { return this.m_SoundRadius; } } | ||
772 | public double priority { get { return this.m_priority; } } | ||
773 | } | ||
774 | |||
775 | public struct UpdatePriorityData { | 574 | public struct UpdatePriorityData { |
776 | private double m_priority; | 575 | private double m_priority; |
777 | private uint m_localID; | 576 | private uint m_localID; |
@@ -785,14 +584,46 @@ namespace OpenSim.Framework | |||
785 | public uint localID { get { return this.m_localID; } } | 584 | public uint localID { get { return this.m_localID; } } |
786 | } | 585 | } |
787 | 586 | ||
587 | /// <summary> | ||
588 | /// Specifies the fields that have been changed when sending a prim or | ||
589 | /// avatar update | ||
590 | /// </summary> | ||
788 | [Flags] | 591 | [Flags] |
789 | public enum StateUpdateTypes | 592 | public enum PrimUpdateFlags : uint |
790 | { | 593 | { |
791 | None = 0, | 594 | None = 0, |
792 | AvatarTerse = 1, | 595 | AttachmentPoint = 1 << 0, |
793 | PrimitiveTerse = AvatarTerse << 1, | 596 | Material = 1 << 1, |
794 | PrimitiveFull = PrimitiveTerse << 1, | 597 | ClickAction = 1 << 2, |
795 | All = AvatarTerse | PrimitiveTerse | PrimitiveFull, | 598 | Scale = 1 << 3, |
599 | ParentID = 1 << 4, | ||
600 | PrimFlags = 1 << 5, | ||
601 | PrimData = 1 << 6, | ||
602 | MediaURL = 1 << 7, | ||
603 | ScratchPad = 1 << 8, | ||
604 | Textures = 1 << 9, | ||
605 | TextureAnim = 1 << 10, | ||
606 | NameValue = 1 << 11, | ||
607 | Position = 1 << 12, | ||
608 | Rotation = 1 << 13, | ||
609 | Velocity = 1 << 14, | ||
610 | Acceleration = 1 << 15, | ||
611 | AngularVelocity = 1 << 16, | ||
612 | CollisionPlane = 1 << 17, | ||
613 | Text = 1 << 18, | ||
614 | Particles = 1 << 19, | ||
615 | ExtraData = 1 << 20, | ||
616 | Sound = 1 << 21, | ||
617 | Joint = 1 << 22, | ||
618 | FullUpdate = UInt32.MaxValue | ||
619 | } | ||
620 | |||
621 | public static class PrimUpdateFlagsExtensions | ||
622 | { | ||
623 | public static bool HasFlag(this PrimUpdateFlags updateFlags, PrimUpdateFlags flag) | ||
624 | { | ||
625 | return (updateFlags & flag) == flag; | ||
626 | } | ||
796 | } | 627 | } |
797 | 628 | ||
798 | public interface IClientAPI | 629 | public interface IClientAPI |
@@ -1186,27 +1017,20 @@ namespace OpenSim.Framework | |||
1186 | void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); | 1017 | void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); |
1187 | void SendPayPrice(UUID objectID, int[] payPrice); | 1018 | void SendPayPrice(UUID objectID, int[] payPrice); |
1188 | 1019 | ||
1189 | void SendAvatarData(SendAvatarData data); | ||
1190 | |||
1191 | void SendAvatarTerseUpdate(SendAvatarTerseData data); | ||
1192 | |||
1193 | void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); | 1020 | void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); |
1194 | 1021 | ||
1195 | void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); | 1022 | void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); |
1196 | void SetChildAgentThrottle(byte[] throttle); | 1023 | void SetChildAgentThrottle(byte[] throttle); |
1197 | 1024 | ||
1198 | void SendPrimitiveToClient(SendPrimitiveData data); | 1025 | void SendAvatarDataImmediate(ISceneEntity avatar); |
1199 | 1026 | void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags); | |
1200 | void SendPrimTerseUpdate(SendPrimitiveTerseData data); | 1027 | void ReprioritizeUpdates(UpdatePriorityHandler handler); |
1201 | 1028 | void FlushPrimUpdates(); | |
1202 | void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler); | ||
1203 | 1029 | ||
1204 | void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, | 1030 | void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, |
1205 | List<InventoryFolderBase> folders, int version, bool fetchFolders, | 1031 | List<InventoryFolderBase> folders, int version, bool fetchFolders, |
1206 | bool fetchItems); | 1032 | bool fetchItems); |
1207 | 1033 | ||
1208 | void FlushPrimUpdates(); | ||
1209 | |||
1210 | void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item); | 1034 | void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item); |
1211 | 1035 | ||
1212 | /// <summary> | 1036 | /// <summary> |
diff --git a/OpenSim/Framework/ISceneEntity.cs b/OpenSim/Framework/ISceneEntity.cs new file mode 100644 index 0000000..fa3c514 --- /dev/null +++ b/OpenSim/Framework/ISceneEntity.cs | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using OpenMetaverse; | ||
29 | |||
30 | namespace OpenSim.Framework | ||
31 | { | ||
32 | public interface ISceneEntity | ||
33 | { | ||
34 | UUID UUID { get; } | ||
35 | uint LocalId { get; } | ||
36 | } | ||
37 | } | ||
diff --git a/OpenSim/Framework/Lazy.cs b/OpenSim/Framework/Lazy.cs new file mode 100644 index 0000000..8a417ac --- /dev/null +++ b/OpenSim/Framework/Lazy.cs | |||
@@ -0,0 +1,236 @@ | |||
1 | // | ||
2 | // Lazy.cs | ||
3 | // | ||
4 | // Authors: | ||
5 | // Zoltan Varga (vargaz@gmail.com) | ||
6 | // Marek Safar (marek.safar@gmail.com) | ||
7 | // | ||
8 | // Copyright (C) 2009 Novell | ||
9 | // | ||
10 | // Permission is hereby granted, free of charge, to any person obtaining | ||
11 | // a copy of this software and associated documentation files (the | ||
12 | // "Software"), to deal in the Software without restriction, including | ||
13 | // without limitation the rights to use, copy, modify, merge, publish, | ||
14 | // distribute, sublicense, and/or sell copies of the Software, and to | ||
15 | // permit persons to whom the Software is furnished to do so, subject to | ||
16 | // the following conditions: | ||
17 | // | ||
18 | // The above copyright notice and this permission notice shall be | ||
19 | // included in all copies or substantial portions of the Software. | ||
20 | // | ||
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
28 | // | ||
29 | |||
30 | using System; | ||
31 | using System.Runtime.Serialization; | ||
32 | using System.Runtime.InteropServices; | ||
33 | using System.Security.Permissions; | ||
34 | using System.Threading; | ||
35 | using System.Diagnostics; | ||
36 | |||
37 | namespace OpenSim.Framework | ||
38 | { | ||
39 | public enum LazyThreadSafetyMode | ||
40 | { | ||
41 | None, | ||
42 | PublicationOnly, | ||
43 | ExecutionAndPublication | ||
44 | } | ||
45 | |||
46 | [SerializableAttribute] | ||
47 | [ComVisibleAttribute(false)] | ||
48 | [HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] | ||
49 | public class Lazy<T> | ||
50 | { | ||
51 | T value; | ||
52 | bool inited; | ||
53 | LazyThreadSafetyMode mode; | ||
54 | Func<T> factory; | ||
55 | object monitor; | ||
56 | Exception exception; | ||
57 | |||
58 | public Lazy() | ||
59 | : this(LazyThreadSafetyMode.ExecutionAndPublication) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | public Lazy(Func<T> valueFactory) | ||
64 | : this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | public Lazy(bool isThreadSafe) | ||
69 | : this(() => Activator.CreateInstance<T>(), isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None) | ||
70 | { | ||
71 | } | ||
72 | |||
73 | public Lazy(Func<T> valueFactory, bool isThreadSafe) | ||
74 | : this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None) | ||
75 | { | ||
76 | } | ||
77 | |||
78 | public Lazy(LazyThreadSafetyMode mode) | ||
79 | : this(() => Activator.CreateInstance<T>(), mode) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode) | ||
84 | { | ||
85 | if (valueFactory == null) | ||
86 | throw new ArgumentNullException("valueFactory"); | ||
87 | this.factory = valueFactory; | ||
88 | if (mode != LazyThreadSafetyMode.None) | ||
89 | monitor = new object(); | ||
90 | this.mode = mode; | ||
91 | } | ||
92 | |||
93 | // Don't trigger expensive initialization | ||
94 | [DebuggerBrowsable(DebuggerBrowsableState.Never)] | ||
95 | public T Value | ||
96 | { | ||
97 | get | ||
98 | { | ||
99 | if (inited) | ||
100 | return value; | ||
101 | if (exception != null) | ||
102 | throw exception; | ||
103 | |||
104 | return InitValue(); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | T InitValue() | ||
109 | { | ||
110 | switch (mode) | ||
111 | { | ||
112 | case LazyThreadSafetyMode.None: | ||
113 | { | ||
114 | var init_factory = factory; | ||
115 | if (init_factory == null) | ||
116 | throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance"); | ||
117 | try | ||
118 | { | ||
119 | factory = null; | ||
120 | T v = init_factory(); | ||
121 | value = v; | ||
122 | Thread.MemoryBarrier(); | ||
123 | inited = true; | ||
124 | } | ||
125 | catch (Exception ex) | ||
126 | { | ||
127 | exception = ex; | ||
128 | throw; | ||
129 | } | ||
130 | break; | ||
131 | } | ||
132 | case LazyThreadSafetyMode.PublicationOnly: | ||
133 | { | ||
134 | var init_factory = factory; | ||
135 | T v; | ||
136 | |||
137 | //exceptions are ignored | ||
138 | if (init_factory != null) | ||
139 | v = init_factory(); | ||
140 | else | ||
141 | v = default(T); | ||
142 | |||
143 | lock (monitor) | ||
144 | { | ||
145 | if (inited) | ||
146 | return value; | ||
147 | value = v; | ||
148 | Thread.MemoryBarrier(); | ||
149 | inited = true; | ||
150 | factory = null; | ||
151 | } | ||
152 | break; | ||
153 | } | ||
154 | case LazyThreadSafetyMode.ExecutionAndPublication: | ||
155 | { | ||
156 | lock (monitor) | ||
157 | { | ||
158 | if (inited) | ||
159 | return value; | ||
160 | |||
161 | if (factory == null) | ||
162 | throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance"); | ||
163 | |||
164 | var init_factory = factory; | ||
165 | try | ||
166 | { | ||
167 | factory = null; | ||
168 | T v = init_factory(); | ||
169 | value = v; | ||
170 | Thread.MemoryBarrier(); | ||
171 | inited = true; | ||
172 | } | ||
173 | catch (Exception ex) | ||
174 | { | ||
175 | exception = ex; | ||
176 | throw; | ||
177 | } | ||
178 | } | ||
179 | break; | ||
180 | } | ||
181 | default: | ||
182 | throw new InvalidOperationException("Invalid LazyThreadSafetyMode " + mode); | ||
183 | } | ||
184 | |||
185 | if (monitor == null) | ||
186 | { | ||
187 | value = factory(); | ||
188 | inited = true; | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | lock (monitor) | ||
193 | { | ||
194 | if (inited) | ||
195 | return value; | ||
196 | |||
197 | if (factory == null) | ||
198 | throw new InvalidOperationException("The initialization function tries to access Value on this instance"); | ||
199 | |||
200 | var init_factory = factory; | ||
201 | try | ||
202 | { | ||
203 | factory = null; | ||
204 | T v = init_factory(); | ||
205 | value = v; | ||
206 | Thread.MemoryBarrier(); | ||
207 | inited = true; | ||
208 | } | ||
209 | catch | ||
210 | { | ||
211 | factory = init_factory; | ||
212 | throw; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | return value; | ||
218 | } | ||
219 | |||
220 | public bool IsValueCreated | ||
221 | { | ||
222 | get | ||
223 | { | ||
224 | return inited; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | public override string ToString() | ||
229 | { | ||
230 | if (inited) | ||
231 | return value.ToString(); | ||
232 | else | ||
233 | return "Value is not created"; | ||
234 | } | ||
235 | } | ||
236 | } | ||