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; } }
};
}