ROOT logo
// $Id: ZNameMap.cxx 2606 2011-12-07 23:11:39Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "ZNameMap.h"
#include "ZNameMap.c7"

typedef pair<TString,lpZGlass_i>           Name2LIter_p;

//______________________________________________________________________________
//
// Keeps a parallel multi-map with elements sorted by their name.
// This is used both to have faster "by-name" search and to
// allow for lists sorted by name.
//
// Registers itself to each element of the map to receive name-change
// callback. This mechanism is rather flawed - it should be extended
// significanly to become bullet-proof:
//   - name-change and consumer registration should be locked (per queen?);
//   - name-change notifications should be sent as MIRs;
//   - the sun copy should handle all this, moon copies should be updated
//     by special MIRs;
//   - all this implies that name-change registration would only be done at
//     the sun.
// Oh, also, the insertions should be done at the sun with some more specific
// MIR being sent to the moons.
//
// The bKeepSorted flag enforces that the list remains sorted by name
// most of the time (the request is sent via a MIR). This is primarily
// intended for GUI views. This could also be improved with the above changes.

ClassImp(ZNameMap);

//------------------------------------------------------------------------------

void ZNameMap::_init()
{
  bKeepSorted    = false;
  bWarnEqualName = false;
}

ZNameMap::ZNameMap(const Text_t* n, const Text_t* t) : ZList(n,t)
{
  _init();
}

ZNameMap::~ZNameMap()
{}

//------------------------------------------------------------------------------

void ZNameMap::new_element_check(ZGlass* lens)
{
  static const Exc_t _eh("ZNameMap::new_element_check ");

  PARENT_GLASS::new_element_check(lens);

  mName2Iter_i i = mItMap.find(lens->StrName());
  if(i != mItMap.end() && bWarnEqualName) {
    // Could in principle deny request.
    // The problem is I can do no such thing in name_change_cb. Well,
    // one could shoot a mir requesting removal of one or the other entry.
    ISwarn(_eh + "lens with the same name as '" + lens->Identify() + "' already in the map.");
  }
}

void ZNameMap::clear_list()
{
  for(ZList::iterator i=begin(); i!=end(); ++i)
    i.lens()->unregister_name_change_cb(this);
  PARENT_GLASS::clear_list();
  mItMap.clear();
}

//------------------------------------------------------------------------------

void ZNameMap::on_insert(ZList::iterator it)
{
  it.lens()->register_name_change_cb(this);
  mItMap.insert(make_pair(it.lens()->StrName(), it));
}

void ZNameMap::on_remove(ZList::iterator it)
{
  static const Exc_t _eh("ZNameMap::on_remove ");

  mName2Iter_i_pair range = mItMap.equal_range(it.lens()->StrName());

  if(range.first == range.second) {
    ISwarn(_eh + "*strange*, name not found in the map.");
    return;
  }

  for(mName2Iter_i i = range.first; i != range.second; ++i) {
    if(i->second == it) {
      mItMap.erase(i);
      it.lens()->unregister_name_change_cb(this);
      return;
    }
  }

  // If we get here, match was not found.
  ISwarn(_eh + "*strange*, got uncompatible iterators.");
}

void ZNameMap::on_rebuild()
{
  mItMap.clear();
  for(ZList::iterator i=begin(); i!=end(); ++i) {
    mItMap.insert(make_pair(i.lens()->StrName(), i));
  }
}

//------------------------------------------------------------------------------

void ZNameMap::SetKeepSorted(Bool_t keep_sorted)
{
  if(keep_sorted == bKeepSorted)
    return;

  if(keep_sorted)
    SortByName();

  bKeepSorted = keep_sorted;

  Stamp(FID());
}

//------------------------------------------------------------------------------

ZGlass* ZNameMap::GetElementByName(const TString& name)
{
  GMutexHolder lck(mListMutex);
  mName2Iter_i i = mItMap.find(name);
  return (i != mItMap.end()) ? i->second.lens() : 0;
}

Int_t ZNameMap::GetElementsByName(const TString& name, lpZGlass_t& dest)
{
  Int_t n = 0;
  GMutexHolder lck(mListMutex);
  mName2Iter_i_pair range = mItMap.equal_range(name);
  for(mName2Iter_i i=range.first; i!=range.second; ++i) {
    dest.push_back(i->second.lens());
    ++n;
  }
  return n;
}

//------------------------------------------------------------------------------

void ZNameMap::shoot_sort_mir()
{
  if(IsSunSpace()) {
    auto_ptr<ZMIR> mir(S_SortByName());
    mSaturn->ShootMIR(mir); 
  }
}

void ZNameMap::SortByName()
{
  GMutexHolder llck(mListMutex);
  if(mSize < 2) return;

  list<element> store;
  mElements.swap(store);
  mNextId = 0;
  for(mName2Iter_i i=mItMap.begin(); i!=mItMap.end(); ++i) {
    mElements.push_back(element(i->second.lens(), mNextId++));
    i->second = --mElements.end();
  }
  on_rebuild();
  StampListRebuild();
}

void ZNameMap::DumpNameMap()
{
  static const Exc_t _eh("ZNameMap::DumpNameMap ");

  GMutexHolder list_lock(mListMutex);

  printf("%s %s, mSize=%d\n", _eh.Data(), Identify().Data(), mSize);
  Int_t n = 1;
  for(mName2Iter_i i=mItMap.begin(); i!=mItMap.end(); ++i, ++n)
  {
    printf("%4d '%s'%*c - %s\n", n, i->first.Data(), 20 - i->first.Length(), ' ', i->second()->Identify().Data());
  }
}

//------------------------------------------------------------------------------
// Functions that add elements - bKeepSorted overrides placement
//------------------------------------------------------------------------------

void ZNameMap::insert_with_placement(ZGlass* lens)
{
  static const Exc_t _eh("ZNameMap::insert_with_placement ");

  GMutexHolder llck(mListMutex);
  new_element_check(lens);

  TString name = lens->StrName();

  ZList::iterator i;
  {
    mName2Iter_i nii = mItMap.upper_bound(lens->StrName());
    if (nii == mItMap.end())
      i = mElements.end();
    else
      i = nii->second;
  }
  lens->IncRefCount(this);
  ZList::iterator j = mElements.insert(i, element(lens, mNextId++)); ++mSize;
  on_insert(j);

  if (i == mElements.end())
    StampListPushBack(lens, mNextId-1);
  else
    StampListInsert(lens, mNextId-1, i->fId);
}

void ZNameMap::PushBack(ZGlass* lens)
{
  if (bKeepSorted) {
    insert_with_placement(lens);
  } else {
    ZList::PushBack(lens);
  }
}

void ZNameMap::PushFront(ZGlass* lens)
{
  if (bKeepSorted) {
    insert_with_placement(lens);
  } else {
    ZList::PushFront(lens);
  }
}

void ZNameMap::InsertById(ZGlass* lens, Int_t before_id)
{
  if (bKeepSorted) {
    insert_with_placement(lens);
  } else {
    ZList::InsertById(lens, before_id);
  }
}

//------------------------------------------------------------------------------
// Virtuals from non-glasses
//------------------------------------------------------------------------------

void ZNameMap::name_change_cb(ZGlass* lens, const TString& new_name)
{
  static const Exc_t _eh("ZNameMap::name_change_cb ");

  const TString& old_name(lens->RefName());

  if(new_name == old_name) return;

  GMutexHolder list_lock(mListMutex);

  mName2Iter_i_pair range = mItMap.equal_range(old_name);

  if(range.first == range.second) {
    // This is bad and should NOT happen.
    // No really good way to handle it here ... unless we rescan the whole
    // map and search for the lens via its address.
    ISerr(_eh + "element " + lens->Identify() + " not found in map " + Identify() + ".");
    return;
  }

  if(bWarnEqualName) {
    mName2Iter_i n = mItMap.find(new_name);
    if(n != mItMap.end()) {
      ISwarn(_eh + "element with the same name as '" + lens->Identify() + "' already in the map.");
    }
  }

  list<mName2Iter_pair> newelms;
  for(mName2Iter_i i = range.first; i != range.second;) {
    if(i->second.lens() == lens) {
      newelms.push_back(make_pair(new_name, i->second));
      mName2Iter_i j = i++;
      mItMap.erase(j);
    } else {
      ++i;
    }
  }
  for(list<mName2Iter_pair>::iterator i=newelms.begin(); i!=newelms.end(); ++i)
    mItMap.insert(*i);

  if(bKeepSorted)
    shoot_sort_mir();
}
 ZNameMap.cxx:1
 ZNameMap.cxx:2
 ZNameMap.cxx:3
 ZNameMap.cxx:4
 ZNameMap.cxx:5
 ZNameMap.cxx:6
 ZNameMap.cxx:7
 ZNameMap.cxx:8
 ZNameMap.cxx:9
 ZNameMap.cxx:10
 ZNameMap.cxx:11
 ZNameMap.cxx:12
 ZNameMap.cxx:13
 ZNameMap.cxx:14
 ZNameMap.cxx:15
 ZNameMap.cxx:16
 ZNameMap.cxx:17
 ZNameMap.cxx:18
 ZNameMap.cxx:19
 ZNameMap.cxx:20
 ZNameMap.cxx:21
 ZNameMap.cxx:22
 ZNameMap.cxx:23
 ZNameMap.cxx:24
 ZNameMap.cxx:25
 ZNameMap.cxx:26
 ZNameMap.cxx:27
 ZNameMap.cxx:28
 ZNameMap.cxx:29
 ZNameMap.cxx:30
 ZNameMap.cxx:31
 ZNameMap.cxx:32
 ZNameMap.cxx:33
 ZNameMap.cxx:34
 ZNameMap.cxx:35
 ZNameMap.cxx:36
 ZNameMap.cxx:37
 ZNameMap.cxx:38
 ZNameMap.cxx:39
 ZNameMap.cxx:40
 ZNameMap.cxx:41
 ZNameMap.cxx:42
 ZNameMap.cxx:43
 ZNameMap.cxx:44
 ZNameMap.cxx:45
 ZNameMap.cxx:46
 ZNameMap.cxx:47
 ZNameMap.cxx:48
 ZNameMap.cxx:49
 ZNameMap.cxx:50
 ZNameMap.cxx:51
 ZNameMap.cxx:52
 ZNameMap.cxx:53
 ZNameMap.cxx:54
 ZNameMap.cxx:55
 ZNameMap.cxx:56
 ZNameMap.cxx:57
 ZNameMap.cxx:58
 ZNameMap.cxx:59
 ZNameMap.cxx:60
 ZNameMap.cxx:61
 ZNameMap.cxx:62
 ZNameMap.cxx:63
 ZNameMap.cxx:64
 ZNameMap.cxx:65
 ZNameMap.cxx:66
 ZNameMap.cxx:67
 ZNameMap.cxx:68
 ZNameMap.cxx:69
 ZNameMap.cxx:70
 ZNameMap.cxx:71
 ZNameMap.cxx:72
 ZNameMap.cxx:73
 ZNameMap.cxx:74
 ZNameMap.cxx:75
 ZNameMap.cxx:76
 ZNameMap.cxx:77
 ZNameMap.cxx:78
 ZNameMap.cxx:79
 ZNameMap.cxx:80
 ZNameMap.cxx:81
 ZNameMap.cxx:82
 ZNameMap.cxx:83
 ZNameMap.cxx:84
 ZNameMap.cxx:85
 ZNameMap.cxx:86
 ZNameMap.cxx:87
 ZNameMap.cxx:88
 ZNameMap.cxx:89
 ZNameMap.cxx:90
 ZNameMap.cxx:91
 ZNameMap.cxx:92
 ZNameMap.cxx:93
 ZNameMap.cxx:94
 ZNameMap.cxx:95
 ZNameMap.cxx:96
 ZNameMap.cxx:97
 ZNameMap.cxx:98
 ZNameMap.cxx:99
 ZNameMap.cxx:100
 ZNameMap.cxx:101
 ZNameMap.cxx:102
 ZNameMap.cxx:103
 ZNameMap.cxx:104
 ZNameMap.cxx:105
 ZNameMap.cxx:106
 ZNameMap.cxx:107
 ZNameMap.cxx:108
 ZNameMap.cxx:109
 ZNameMap.cxx:110
 ZNameMap.cxx:111
 ZNameMap.cxx:112
 ZNameMap.cxx:113
 ZNameMap.cxx:114
 ZNameMap.cxx:115
 ZNameMap.cxx:116
 ZNameMap.cxx:117
 ZNameMap.cxx:118
 ZNameMap.cxx:119
 ZNameMap.cxx:120
 ZNameMap.cxx:121
 ZNameMap.cxx:122
 ZNameMap.cxx:123
 ZNameMap.cxx:124
 ZNameMap.cxx:125
 ZNameMap.cxx:126
 ZNameMap.cxx:127
 ZNameMap.cxx:128
 ZNameMap.cxx:129
 ZNameMap.cxx:130
 ZNameMap.cxx:131
 ZNameMap.cxx:132
 ZNameMap.cxx:133
 ZNameMap.cxx:134
 ZNameMap.cxx:135
 ZNameMap.cxx:136
 ZNameMap.cxx:137
 ZNameMap.cxx:138
 ZNameMap.cxx:139
 ZNameMap.cxx:140
 ZNameMap.cxx:141
 ZNameMap.cxx:142
 ZNameMap.cxx:143
 ZNameMap.cxx:144
 ZNameMap.cxx:145
 ZNameMap.cxx:146
 ZNameMap.cxx:147
 ZNameMap.cxx:148
 ZNameMap.cxx:149
 ZNameMap.cxx:150
 ZNameMap.cxx:151
 ZNameMap.cxx:152
 ZNameMap.cxx:153
 ZNameMap.cxx:154
 ZNameMap.cxx:155
 ZNameMap.cxx:156
 ZNameMap.cxx:157
 ZNameMap.cxx:158
 ZNameMap.cxx:159
 ZNameMap.cxx:160
 ZNameMap.cxx:161
 ZNameMap.cxx:162
 ZNameMap.cxx:163
 ZNameMap.cxx:164
 ZNameMap.cxx:165
 ZNameMap.cxx:166
 ZNameMap.cxx:167
 ZNameMap.cxx:168
 ZNameMap.cxx:169
 ZNameMap.cxx:170
 ZNameMap.cxx:171
 ZNameMap.cxx:172
 ZNameMap.cxx:173
 ZNameMap.cxx:174
 ZNameMap.cxx:175
 ZNameMap.cxx:176
 ZNameMap.cxx:177
 ZNameMap.cxx:178
 ZNameMap.cxx:179
 ZNameMap.cxx:180
 ZNameMap.cxx:181
 ZNameMap.cxx:182
 ZNameMap.cxx:183
 ZNameMap.cxx:184
 ZNameMap.cxx:185
 ZNameMap.cxx:186
 ZNameMap.cxx:187
 ZNameMap.cxx:188
 ZNameMap.cxx:189
 ZNameMap.cxx:190
 ZNameMap.cxx:191
 ZNameMap.cxx:192
 ZNameMap.cxx:193
 ZNameMap.cxx:194
 ZNameMap.cxx:195
 ZNameMap.cxx:196
 ZNameMap.cxx:197
 ZNameMap.cxx:198
 ZNameMap.cxx:199
 ZNameMap.cxx:200
 ZNameMap.cxx:201
 ZNameMap.cxx:202
 ZNameMap.cxx:203
 ZNameMap.cxx:204
 ZNameMap.cxx:205
 ZNameMap.cxx:206
 ZNameMap.cxx:207
 ZNameMap.cxx:208
 ZNameMap.cxx:209
 ZNameMap.cxx:210
 ZNameMap.cxx:211
 ZNameMap.cxx:212
 ZNameMap.cxx:213
 ZNameMap.cxx:214
 ZNameMap.cxx:215
 ZNameMap.cxx:216
 ZNameMap.cxx:217
 ZNameMap.cxx:218
 ZNameMap.cxx:219
 ZNameMap.cxx:220
 ZNameMap.cxx:221
 ZNameMap.cxx:222
 ZNameMap.cxx:223
 ZNameMap.cxx:224
 ZNameMap.cxx:225
 ZNameMap.cxx:226
 ZNameMap.cxx:227
 ZNameMap.cxx:228
 ZNameMap.cxx:229
 ZNameMap.cxx:230
 ZNameMap.cxx:231
 ZNameMap.cxx:232
 ZNameMap.cxx:233
 ZNameMap.cxx:234
 ZNameMap.cxx:235
 ZNameMap.cxx:236
 ZNameMap.cxx:237
 ZNameMap.cxx:238
 ZNameMap.cxx:239
 ZNameMap.cxx:240
 ZNameMap.cxx:241
 ZNameMap.cxx:242
 ZNameMap.cxx:243
 ZNameMap.cxx:244
 ZNameMap.cxx:245
 ZNameMap.cxx:246
 ZNameMap.cxx:247
 ZNameMap.cxx:248
 ZNameMap.cxx:249
 ZNameMap.cxx:250
 ZNameMap.cxx:251
 ZNameMap.cxx:252
 ZNameMap.cxx:253
 ZNameMap.cxx:254
 ZNameMap.cxx:255
 ZNameMap.cxx:256
 ZNameMap.cxx:257
 ZNameMap.cxx:258
 ZNameMap.cxx:259
 ZNameMap.cxx:260
 ZNameMap.cxx:261
 ZNameMap.cxx:262
 ZNameMap.cxx:263
 ZNameMap.cxx:264
 ZNameMap.cxx:265
 ZNameMap.cxx:266
 ZNameMap.cxx:267
 ZNameMap.cxx:268
 ZNameMap.cxx:269
 ZNameMap.cxx:270
 ZNameMap.cxx:271
 ZNameMap.cxx:272
 ZNameMap.cxx:273
 ZNameMap.cxx:274
 ZNameMap.cxx:275
 ZNameMap.cxx:276
 ZNameMap.cxx:277
 ZNameMap.cxx:278
 ZNameMap.cxx:279
 ZNameMap.cxx:280
 ZNameMap.cxx:281
 ZNameMap.cxx:282
 ZNameMap.cxx:283
 ZNameMap.cxx:284
 ZNameMap.cxx:285
 ZNameMap.cxx:286
 ZNameMap.cxx:287
 ZNameMap.cxx:288
 ZNameMap.cxx:289
 ZNameMap.cxx:290
 ZNameMap.cxx:291
 ZNameMap.cxx:292
 ZNameMap.cxx:293
 ZNameMap.cxx:294
 ZNameMap.cxx:295
 ZNameMap.cxx:296