using System; using System.Diagnostics; using System.Threading; using miew.Concurrency; using miew.Debugging; #pragma warning disable 0649 namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class Strings { FalseSharing.Padding60 fsp1; int next_string_id = 1; FalseSharing.Padding60 fsp2; readonly ConcurrentSymmetricDictionary<String, Int32> dict = new ConcurrentSymmetricDictionary<String, Int32>(); readonly TypeMgr tm; public int string_id; public bool f_petrified = false; public Strings(TypeMgr tm) { this.tm = tm; Nop.X(fsp1, fsp2); } public void Petrify() { f_petrified = true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Guaranteed to preserve the coreference flag and return an _existing_ string mark, if successful /// Implicitly unifies down to *string* (at least) /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool Unify(int m_recycle, Edge e1, Edge e2, MarkingTfs tfs_dst, out Edge result) { //Debug.Assert((e1.FlagsId & Edge.Flag.EtmMask) == Edge.Flag.EtmString || (e2.FlagsId & Edge.Flag.EtmMask) == Edge.Flag.EtmString); int id1 = (int)(e1.FlagsId & Edge.Flag.MultiIdMask); int id2 = (int)(e2.FlagsId & Edge.Flag.MultiIdMask); Edge.Flag f_coref = ((e1.FlagsId | e2.FlagsId) & Edge.Flag.Coreference); /// check for e1 not being a string type if ((e1.FlagsId & Edge.Flag.EtmMask) != Edge.Flag.EtmString) { if (id1 != 0 && !tm.CanUnify(string_id, id1)) goto failed; id1 = 0; } /// check for e2 not being a string type if ((e2.FlagsId & Edge.Flag.EtmMask) != Edge.Flag.EtmString) { if (id2 != 0 && !tm.CanUnify(string_id, id2)) goto failed; id2 = 0; } /// both are some kind of string if (id2 == 0 || id1 == id2) { result = tfs_dst.CreateRecycledEdge(f_coref | Edge.Flag.EtmString | (Edge.Flag)id1, m_recycle); return true; } if (id1 == 0) { result = tfs_dst.CreateRecycledEdge(f_coref | Edge.Flag.EtmString | (Edge.Flag)id2, m_recycle); return true; } failed: result = default(Edge); return false; } public String Get(Int32 sid) { #if DEBUG String err = CheckId(sid); if (err != null) throw new TypeMgr.InternalConsistencyException(err); #endif return dict[sid]; } public String CheckId(Int32 sid) { if (sid > (int)Edge.Flag.MultiIdMask) return String.Format( "String id {0} (0x{1}) is outside the mask range (0x{2}) that was computed when the type hierarchy was frozen.", sid, sid.ToString("X" + (tm.c_t_bits / 4).ToString()), Edge.Flag.MultiIdMask); if (!dict.ContainsKey(sid)) return String.Format("String id {0} (0x{1}) was not found",sid, sid.ToString("X" + (tm.c_t_bits / 4).ToString())); return null; } public int GetOrAdd(String s) { int sid; if (dict.TryGetKey(s, out sid)) return sid; sid = Interlocked.Increment(ref next_string_id); dict.Add(s, sid); return sid; } public int Count { get { return dict.Count; } } }; }