<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#include <string>

#include <glog/logging.h>

#include <mesos/zookeeper/contender.hpp>
#include <mesos/zookeeper/detector.hpp>
#include <mesos/zookeeper/group.hpp>

#include <process/check.hpp>
#include <process/defer.hpp>
#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/id.hpp>
#include <process/process.hpp>

#include <stout/check.hpp>
#include <stout/lambda.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>

using std::string;

using process::Failure;
using process::Future;
using process::Process;
using process::Promise;

namespace zookeeper {

class LeaderContenderProcess : public Process<LeaderContenderProcess>
{
public:
  LeaderContenderProcess(
      Group* group,
      const string& data,
      const Option<string>& label);

  virtual ~LeaderContenderProcess();

  // LeaderContender implementation.
  Future<Future<Nothing> > contend();
  Future<bool> withdraw();

protected:
  virtual void finalize();

private:
  // Invoked when we have joined the group (or failed to do so).
  void joined();

  // Invoked when the group membership is cancelled.
  void cancelled(const Future<bool>& result);

  // Helper for cancelling the Group membership.
  void cancel();

  Group* group;
  const string data;
  const Option<string> label;

  // The contender's state transitions from contending -> watching ->
  // withdrawing or contending -> withdrawing. Each state is
  // identified by the corresponding Option<Promise> being assigned.
  // Note that these Option<Promise>s are never reset to None once it
  // is assigned.

  // Holds the promise for the future for contend().
  Option<Promise<Future<Nothing> >*> contending;

  // Holds the promise for the inner future enclosed by contend()'s
  // result which is satisfied when the contender's candidacy is
  // lost.
  Option<Promise<Nothing>*> watching;

  // Holds the promise for the future for withdraw().
  Option<Promise<bool>*> withdrawing;

  // Stores the result for joined().
  Future<Group::Membership> candidacy;
};

LeaderContenderProcess::LeaderContenderProcess(
    Group* _group,
    const string& _data,
    const Option<string>& _label)
  : ProcessBase(process::ID::generate("leader-contender")),
    group(_group),
    data(_data),
    label(_label) {}

LeaderContenderProcess::~LeaderContenderProcess()
{
  if (contending.isSome()) {
    contending.get()->discard();
    delete contending.get();
    contending = None();
  }

  if (watching.isSome()) {
    watching.get()->discard();
    delete watching.get();
    watching = None();
  }

  if (withdrawing.isSome()) {
    withdrawing.get()->discard();
    delete withdrawing.get();
    withdrawing = None();
  }
}

void LeaderContenderProcess::finalize()
{
  // We do not wait for the result here because the Group keeps
  // retrying (even after the contender is destroyed) until it
  // succeeds so the old membership is eventually going to be
  // cancelled.
  // There is a tricky situation where the contender terminates after
  // it has contended but before it is notified of the obtained
  // membership. In this case the membership is not cancelled during
  // contender destruction. The client thus should use withdraw() to
  // wait for the membership to be first obtained and then cancelled.
  cancel();
}

Future<Future<Nothing> > LeaderContenderProcess::contend()
{
  if (contending.isSome()) {
    return Failure("Cannot contend more than once");
  }

  LOG(INFO) << "Joining the ZK group";
  candidacy = group->join(data, label);
  candidacy
    .onAny(defer(self(), &Self::joined));

  // Okay, we wait and see what unfolds.
  contending = new Promise<Future<Nothing> >();
  return contending.get()->future();
}

Future<bool> LeaderContenderProcess::withdraw()
{
  if (contending.isNone()) {
    // Nothing to withdraw because the contender has not contended.
    return false;
  }

  if (withdrawing.isSome()) {
    // Repeated calls to withdraw get the same result.
    return withdrawing.get();
  }

  withdrawing = new Promise<bool>();

  CHECK(!candidacy.isDiscarded());

  if (candidacy.isPending()) {
    // If we have not obtained the candidacy yet, we withdraw after
    // it is obtained.
    LOG(INFO) << "Withdraw requested before the candidacy is obtained; will "
              << "withdraw after it happens";
    candidacy.onAny(defer(self(), &Self::cancel));
  } else if (candidacy.isReady()) {
    cancel();
  } else {
    // We have failed to obtain the candidacy so we do not need to
    // cancel it.
    return false;
  }

  return withdrawing.get()->future();
}

void LeaderContenderProcess::cancel()
{
  if (!candidacy.isReady()) {
    // Nothing to cancel.
    if (withdrawing.isSome()) {
      withdrawing.get()->set(false);
    }
    return;
  }

  LOG(INFO) << "Now cancelling the membership: " << candidacy.get().id();

  group->cancel(candidacy.get())
    .onAny(defer(self(), &Self::cancelled, lambda::_1));
}

void LeaderContenderProcess::cancelled(const Future<bool>& result)
{
  CHECK_READY(candidacy);
  LOG(INFO) << "Membership cancelled: " << candidacy.get().id();

  // Can be called as a result of either withdraw() or server side
  // expiration.
  CHECK(withdrawing.isSome() || watching.isSome());

  CHECK(!result.isDiscarded());

  if (result.isFailed()) {
    if (withdrawing.isSome()) {
      withdrawing.get()->fail(result.failure());
    }

    if (watching.isSome()) {
      watching.get()->fail(result.failure());
    }
  } else {
    if (withdrawing.isSome()) {
      withdrawing.get()->set(result);
    }

    if (watching.isSome()) {
      watching.get()->set(Nothing());
    }
  }
}

void LeaderContenderProcess::joined()
{
  CHECK(!candidacy.isDiscarded());

  // Cannot be watching because the candidacy is not obtained yet.
  CHECK_NONE(watching);

  CHECK_SOME(contending);

  if (candidacy.isFailed()) {
    // The promise 'withdrawing' will be set to false in cancel().
    contending.get()->fail(candidacy.failure());
    return;
  }

  if (withdrawing.isSome()) {
    LOG(INFO) << "Joined group after the contender started withdrawing";

    // The promise 'withdrawing' will be set to 'false' in subsequent
    // 'cancel()' call.
    return;
  }

  LOG(INFO) << "New candidate (id='" << candidacy.get().id()
            << "') has entered the contest for leadership";

  // Transition to 'watching' state.
  watching = new Promise<Nothing>();

  // Notify the client.
  if (contending.get()->set(watching.get()->future())) {
    // Continue to watch that our membership is not removed (if the
    // client still cares about it).
    candidacy.get().cancelled()
      .onAny(defer(self(), &Self::cancelled, lambda::_1));
  }
}

LeaderContender::LeaderContender(
    Group* group,
    const string& data,
    const Option<string>& label)
{
  process = new LeaderContenderProcess(group, data, label);
  spawn(process);
}

LeaderContender::~LeaderContender()
{
  terminate(process);
  process::wait(process);
  delete process;
}

Future<Future<Nothing> > LeaderContender::contend()
{
  return dispatch(process, &LeaderContenderProcess::contend);
}

Future<bool> LeaderContender::withdraw()
{
  return dispatch(process, &LeaderContenderProcess::withdraw);
}

} // namespace zookeeper {
<commit_msg>Cleaned up angle brackets in "zookeeper/contender.cpp".<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#include <string>

#include <glog/logging.h>

#include <mesos/zookeeper/contender.hpp>
#include <mesos/zookeeper/detector.hpp>
#include <mesos/zookeeper/group.hpp>

#include <process/check.hpp>
#include <process/defer.hpp>
#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/id.hpp>
#include <process/process.hpp>

#include <stout/check.hpp>
#include <stout/lambda.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>

using std::string;

using process::Failure;
using process::Future;
using process::Process;
using process::Promise;

namespace zookeeper {

class LeaderContenderProcess : public Process<LeaderContenderProcess>
{
public:
  LeaderContenderProcess(
      Group* group,
      const string& data,
      const Option<string>& label);

  virtual ~LeaderContenderProcess();

  // LeaderContender implementation.
  Future<Future<Nothing>> contend();
  Future<bool> withdraw();

protected:
  virtual void finalize();

private:
  // Invoked when we have joined the group (or failed to do so).
  void joined();

  // Invoked when the group membership is cancelled.
  void cancelled(const Future<bool>& result);

  // Helper for cancelling the Group membership.
  void cancel();

  Group* group;
  const string data;
  const Option<string> label;

  // The contender's state transitions from contending -> watching ->
  // withdrawing or contending -> withdrawing. Each state is
  // identified by the corresponding Option<Promise> being assigned.
  // Note that these Option<Promise>s are never reset to None once it
  // is assigned.

  // Holds the promise for the future for contend().
  Option<Promise<Future<Nothing>>*> contending;

  // Holds the promise for the inner future enclosed by contend()'s
  // result which is satisfied when the contender's candidacy is
  // lost.
  Option<Promise<Nothing>*> watching;

  // Holds the promise for the future for withdraw().
  Option<Promise<bool>*> withdrawing;

  // Stores the result for joined().
  Future<Group::Membership> candidacy;
};

LeaderContenderProcess::LeaderContenderProcess(
    Group* _group,
    const string& _data,
    const Option<string>& _label)
  : ProcessBase(process::ID::generate("leader-contender")),
    group(_group),
    data(_data),
    label(_label) {}

LeaderContenderProcess::~LeaderContenderProcess()
{
  if (contending.isSome()) {
    contending.get()->discard();
    delete contending.get();
    contending = None();
  }

  if (watching.isSome()) {
    watching.get()->discard();
    delete watching.get();
    watching = None();
  }

  if (withdrawing.isSome()) {
    withdrawing.get()->discard();
    delete withdrawing.get();
    withdrawing = None();
  }
}

void LeaderContenderProcess::finalize()
{
  // We do not wait for the result here because the Group keeps
  // retrying (even after the contender is destroyed) until it
  // succeeds so the old membership is eventually going to be
  // cancelled.
  // There is a tricky situation where the contender terminates after
  // it has contended but before it is notified of the obtained
  // membership. In this case the membership is not cancelled during
  // contender destruction. The client thus should use withdraw() to
  // wait for the membership to be first obtained and then cancelled.
  cancel();
}

Future<Future<Nothing>> LeaderContenderProcess::contend()
{
  if (contending.isSome()) {
    return Failure("Cannot contend more than once");
  }

  LOG(INFO) << "Joining the ZK group";
  candidacy = group->join(data, label);
  candidacy
    .onAny(defer(self(), &Self::joined));

  // Okay, we wait and see what unfolds.
  contending = new Promise<Future<Nothing>>();
  return contending.get()->future();
}

Future<bool> LeaderContenderProcess::withdraw()
{
  if (contending.isNone()) {
    // Nothing to withdraw because the contender has not contended.
    return false;
  }

  if (withdrawing.isSome()) {
    // Repeated calls to withdraw get the same result.
    return withdrawing.get();
  }

  withdrawing = new Promise<bool>();

  CHECK(!candidacy.isDiscarded());

  if (candidacy.isPending()) {
    // If we have not obtained the candidacy yet, we withdraw after
    // it is obtained.
    LOG(INFO) << "Withdraw requested before the candidacy is obtained; will "
              << "withdraw after it happens";
    candidacy.onAny(defer(self(), &Self::cancel));
  } else if (candidacy.isReady()) {
    cancel();
  } else {
    // We have failed to obtain the candidacy so we do not need to
    // cancel it.
    return false;
  }

  return withdrawing.get()->future();
}

void LeaderContenderProcess::cancel()
{
  if (!candidacy.isReady()) {
    // Nothing to cancel.
    if (withdrawing.isSome()) {
      withdrawing.get()->set(false);
    }
    return;
  }

  LOG(INFO) << "Now cancelling the membership: " << candidacy.get().id();

  group->cancel(candidacy.get())
    .onAny(defer(self(), &Self::cancelled, lambda::_1));
}

void LeaderContenderProcess::cancelled(const Future<bool>& result)
{
  CHECK_READY(candidacy);
  LOG(INFO) << "Membership cancelled: " << candidacy.get().id();

  // Can be called as a result of either withdraw() or server side
  // expiration.
  CHECK(withdrawing.isSome() || watching.isSome());

  CHECK(!result.isDiscarded());

  if (result.isFailed()) {
    if (withdrawing.isSome()) {
      withdrawing.get()->fail(result.failure());
    }

    if (watching.isSome()) {
      watching.get()->fail(result.failure());
    }
  } else {
    if (withdrawing.isSome()) {
      withdrawing.get()->set(result);
    }

    if (watching.isSome()) {
      watching.get()->set(Nothing());
    }
  }
}

void LeaderContenderProcess::joined()
{
  CHECK(!candidacy.isDiscarded());

  // Cannot be watching because the candidacy is not obtained yet.
  CHECK_NONE(watching);

  CHECK_SOME(contending);

  if (candidacy.isFailed()) {
    // The promise 'withdrawing' will be set to false in cancel().
    contending.get()->fail(candidacy.failure());
    return;
  }

  if (withdrawing.isSome()) {
    LOG(INFO) << "Joined group after the contender started withdrawing";

    // The promise 'withdrawing' will be set to 'false' in subsequent
    // 'cancel()' call.
    return;
  }

  LOG(INFO) << "New candidate (id='" << candidacy.get().id()
            << "') has entered the contest for leadership";

  // Transition to 'watching' state.
  watching = new Promise<Nothing>();

  // Notify the client.
  if (contending.get()->set(watching.get()->future())) {
    // Continue to watch that our membership is not removed (if the
    // client still cares about it).
    candidacy.get().cancelled()
      .onAny(defer(self(), &Self::cancelled, lambda::_1));
  }
}

LeaderContender::LeaderContender(
    Group* group,
    const string& data,
    const Option<string>& label)
{
  process = new LeaderContenderProcess(group, data, label);
  spawn(process);
}

LeaderContender::~LeaderContender()
{
  terminate(process);
  process::wait(process);
  delete process;
}

Future<Future<Nothing>> LeaderContender::contend()
{
  return dispatch(process, &LeaderContenderProcess::contend);
}

Future<bool> LeaderContender::withdraw()
{
  return dispatch(process, &LeaderContenderProcess::withdraw);
}

} // namespace zookeeper {
<|endoftext|>


<commit_before><commit_msg>sw: clean up odd formatting<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dflyobj.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: aw $ $Date: 2000-11-25 19:00:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _DFLYOBJ_HXX
#define _DFLYOBJ_HXX

#ifndef _SVDOVIRT_HXX //autogen
#include <svx/svdovirt.hxx>
#endif
#ifndef _SVDOBJ_HXX //autogen
#include <svx/svdobj.hxx>
#endif

class SwFlyFrm;
class SwFrmFmt;
class SdrObjMacroHitRec;

const UINT32 SWGInventor =  UINT32('S')*0x00000001+
                            UINT32('W')*0x00000100+
                            UINT32('G')*0x00010000;

const UINT16 SwFlyDrawObjIdentifier = 0x0001;
const UINT16 SwDrawFirst            = 0x0001;

//---------------------------------------
//SwFlyDrawObj, Die DrawObjekte fuer Flys.

class SwFlyDrawObj : public SdrObject
{
    SfxItemSet*                 mpLocalItemSet;

public:
    TYPEINFO();

    SwFlyDrawObj();
    ~SwFlyDrawObj();

    virtual FASTBOOL Paint(ExtOutputDevice& rOut, const SdrPaintInfoRec& rInfoRec) const;

    // ItemSet access
    virtual const SfxItemSet& GetItemSet() const;
    virtual SfxItemSet* CreateNewItemSet(SfxItemPool& rPool);

    //Damit eine Instanz dieser Klasse beim laden erzeugt werden kann
    //(per Factory).
    virtual UINT32 GetObjInventor()     const;
    virtual UINT16 GetObjIdentifier()   const;
    virtual UINT16 GetObjVersion()      const;
};

//---------------------------------------
//SwVirtFlyDrawObj, die virtuellen Objekte fuer Flys.
//Flys werden immer mit virtuellen Objekten angezeigt. Nur so koennen sie
//ggf. mehrfach angezeigt werden (Kopf-/Fusszeilen).

class SwVirtFlyDrawObj : public SdrVirtObj
{
    SwFlyFrm *pFlyFrm;

public:
    TYPEINFO();

    SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly);
    ~SwVirtFlyDrawObj();

    //Ueberladene Methoden der Basisklasse SdrVirtObj
    virtual SdrObject* CheckHit(const Point& rPnt, USHORT nTol, const SetOfByte* pVisiLayer) const;
    virtual FASTBOOL Paint(ExtOutputDevice& rOut, const SdrPaintInfoRec& rInfoRec) const;
    virtual void     TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const;

    //Wir nehemen die Groessenbehandlung vollstaendig selbst in die Hand.
    virtual const Rectangle& GetBoundRect() const;
    virtual       void       RecalcBoundRect();
    virtual       void       RecalcSnapRect();
    virtual const Rectangle& GetSnapRect()  const;
    virtual       void       SetSnapRect(const Rectangle& rRect);
    virtual       void       NbcSetSnapRect(const Rectangle& rRect);
    virtual const Rectangle& GetLogicRect() const;
    virtual       void       SetLogicRect(const Rectangle& rRect);
    virtual       void       NbcSetLogicRect(const Rectangle& rRect);
    virtual       void       TakeXorPoly(XPolyPolygon& rPoly, FASTBOOL) const;
    virtual       void       NbcMove  (const Size& rSiz);
    virtual       void       NbcResize(const Point& rRef, const Fraction& xFact,
                                       const Fraction& yFact);
    virtual       void       Move  (const Size& rSiz);
    virtual       void       Resize(const Point& rRef, const Fraction& xFact,
                                    const Fraction& yFact);

    const SwFrmFmt *GetFmt() const;
          SwFrmFmt *GetFmt();

    // Get Methoden fuer die Fly Verpointerung
          SwFlyFrm* GetFlyFrm()         { return pFlyFrm; }
    const SwFlyFrm* GetFlyFrm() const   { return pFlyFrm; }

    void SetRect() const;
    void _SetRectsDirty()               { SetRectsDirty(); }

    // ist eine URL an einer Grafik gesetzt, dann ist das ein Makro-Object
    virtual FASTBOOL HasMacro() const;
    virtual SdrObject* CheckMacroHit       (const SdrObjMacroHitRec& rRec) const;
    virtual Pointer    GetMacroPointer     (const SdrObjMacroHitRec& rRec) const;
};

#endif
<commit_msg>INTEGRATION: CWS aw003 (1.2.218); FILE MERGED 2003/10/23 14:39:26 aw 1.2.218.5: #111111# Changed GetBoundRect() to GetCurrentBoundRect() and GetLastBoundRect() 2003/10/07 11:34:04 aw 1.2.218.4: #111097# 2003/07/25 16:21:59 aw 1.2.218.3: #110094# Changed Paint calls on objects to DoPaintObject to identify such cases 2003/05/26 13:19:30 aw 1.2.218.2: #109820# Changed from Properties to BaseProperties 2003/05/21 11:52:01 aw 1.2.218.1: #109820#<commit_after>/*************************************************************************
 *
 *  $RCSfile: dflyobj.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2003-11-24 16:04:11 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _DFLYOBJ_HXX
#define _DFLYOBJ_HXX

#ifndef _SVDOVIRT_HXX //autogen
#include <svx/svdovirt.hxx>
#endif
#ifndef _SVDOBJ_HXX //autogen
#include <svx/svdobj.hxx>
#endif

class SwFlyFrm;
class SwFrmFmt;
class SdrObjMacroHitRec;

const UINT32 SWGInventor =  UINT32('S')*0x00000001+
                            UINT32('W')*0x00000100+
                            UINT32('G')*0x00010000;

const UINT16 SwFlyDrawObjIdentifier = 0x0001;
const UINT16 SwDrawFirst            = 0x0001;

//---------------------------------------
//SwFlyDrawObj, Die DrawObjekte fuer Flys.

class SwFlyDrawObj : public SdrObject
{
    virtual sdr::properties::BaseProperties* CreateObjectSpecificProperties();

public:
    TYPEINFO();

    SwFlyDrawObj();
    ~SwFlyDrawObj();

    virtual sal_Bool DoPaintObject(ExtOutputDevice& rOut, const SdrPaintInfoRec& rInfoRec) const;

    //Damit eine Instanz dieser Klasse beim laden erzeugt werden kann
    //(per Factory).
    virtual UINT32 GetObjInventor()     const;
    virtual UINT16 GetObjIdentifier()   const;
    virtual UINT16 GetObjVersion()      const;
};

//---------------------------------------
//SwVirtFlyDrawObj, die virtuellen Objekte fuer Flys.
//Flys werden immer mit virtuellen Objekten angezeigt. Nur so koennen sie
//ggf. mehrfach angezeigt werden (Kopf-/Fusszeilen).

class SwVirtFlyDrawObj : public SdrVirtObj
{
    SwFlyFrm *pFlyFrm;

public:
    TYPEINFO();

    SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly);
    ~SwVirtFlyDrawObj();

    //Ueberladene Methoden der Basisklasse SdrVirtObj
    virtual SdrObject* CheckHit(const Point& rPnt, USHORT nTol, const SetOfByte* pVisiLayer) const;
    virtual sal_Bool DoPaintObject(ExtOutputDevice& rOut, const SdrPaintInfoRec& rInfoRec) const;
    virtual void     TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const;

    //Wir nehemen die Groessenbehandlung vollstaendig selbst in die Hand.
    virtual const Rectangle& GetCurrentBoundRect() const;
    virtual       void       RecalcBoundRect();
    virtual       void       RecalcSnapRect();
    virtual const Rectangle& GetSnapRect()  const;
    virtual       void       SetSnapRect(const Rectangle& rRect);
    virtual       void       NbcSetSnapRect(const Rectangle& rRect);
    virtual const Rectangle& GetLogicRect() const;
    virtual       void       SetLogicRect(const Rectangle& rRect);
    virtual       void       NbcSetLogicRect(const Rectangle& rRect);
    virtual       void       TakeXorPoly(XPolyPolygon& rPoly, FASTBOOL) const;
    virtual       void       NbcMove  (const Size& rSiz);
    virtual       void       NbcResize(const Point& rRef, const Fraction& xFact,
                                       const Fraction& yFact);
    virtual       void       Move  (const Size& rSiz);
    virtual       void       Resize(const Point& rRef, const Fraction& xFact,
                                    const Fraction& yFact);

    const SwFrmFmt *GetFmt() const;
          SwFrmFmt *GetFmt();

    // Get Methoden fuer die Fly Verpointerung
          SwFlyFrm* GetFlyFrm()         { return pFlyFrm; }
    const SwFlyFrm* GetFlyFrm() const   { return pFlyFrm; }

    void SetRect() const;
    void _SetRectsDirty()               { SetRectsDirty(); }

    // ist eine URL an einer Grafik gesetzt, dann ist das ein Makro-Object
    virtual FASTBOOL HasMacro() const;
    virtual SdrObject* CheckMacroHit       (const SdrObjMacroHitRec& rRec) const;
    virtual Pointer    GetMacroPointer     (const SdrObjMacroHitRec& rRec) const;
};

#endif
<|endoftext|>


<commit_before>#ifndef APOLLO_FUNCTION_HPP_INCLUDED
#define APOLLO_FUNCTION_HPP_INCLUDED APOLLO_FUNCTION_HPP_INCLUDED

#include <apollo/lapi.hpp>
#include <apollo/make_function.hpp>
#include <apollo/reference.hpp>
#include <apollo/stack_balance.hpp>

namespace apollo {

namespace detail {

std::type_info const& function_type(lua_State* L, int idx);

// function_converter //

template <typename F, typename Enable=void>
struct function_converter;

template <template<class> class FObj, typename R, typename... Args>
struct function_converter<FObj<R(Args...)>> {
    using type = FObj<R(Args...)>;

    static type from_stack(lua_State* L, int idx)
    {
        auto const& fty = function_type(L, idx);
        if (fty == typeid(type)) {
            stack_balance balance(L);
            BOOST_VERIFY(lua_getupvalue(L, idx, detail::fn_upval_fn));
            BOOST_ASSERT(lua_type(L, -1) == LUA_TUSERDATA); // Not light!
            return *static_cast<type*>(lua_touserdata(L, -1));
        }

        // Plain function pointer in Lua? Then construct from it.
        using plainfconv = function_converter<R(*)(Args...)>;
        if (fty == typeid(typename plainfconv::type))
            return plainfconv::from_stack(L, idx);

        // TODO?: optimization: Before falling back to the pcall lambda,
        // try boost::function and std::function.

        registry_reference luaFunction(L, idx, ref_mode::copy);
        return [luaFunction](Args... args) -> R {
            lua_State* L_ = luaFunction.L();
            stack_balance b(L_);
            luaFunction.push();
            // Use push_impl to allow empty Args.
            push_impl(L_, std::forward<Args>(args)...);
            pcall(L_, sizeof...(Args), 1);
            return apollo::from_stack<R>(L_, -1);
        };
    }

    static unsigned n_conversion_steps(lua_State* L, int idx)
    {
        if (lua_isfunction(L, idx))
            return 0;
        if (luaL_getmetafield(L, idx, "__call")) { // TODO: pcall
            lua_pop(L, 1);
            return 2;
        }
        return no_conversion;
    }
};

template <typename F>
struct function_converter<F, typename std::enable_if<
        detail::is_plain_function<F>::value ||
        std::is_member_function_pointer<F>::value>::type>
{
    using type = F;

    using is_light = is_light_function<F>;

    static F from_stack(lua_State* L, int idx)
    {
        stack_balance balance(L);
        BOOST_VERIFY(lua_getupvalue(L, idx, fn_upval_fn));
        BOOST_ASSERT(lua_isuserdata(L, -1));
        void* ud = lua_touserdata(L, -1);
        return from_stack_impl(ud, is_light());
    }

    static unsigned n_conversion_steps(lua_State* L, int idx)
    {
        return function_type(L, idx) == typeid(type) ? 0 : no_conversion;
    }

private:
    // Light function:
    static F from_stack_impl(void* ud, std::true_type)
    {
        return reinterpret_cast<light_function_holder<F>&>(ud).f;
    }

    // Non-light function:
    static F& from_stack_impl(void* ud, std::false_type)
    {
        return *static_cast<F*>(ud);
    }
};

} // namespace detail

// Function converter //
template<typename T>
struct converter<T, typename std::enable_if<
        detail::lua_type_id<T>::value == LUA_TFUNCTION>::type>
    : converter_base<T> {

private:
    using fconverter = detail::function_converter<T>;

public:
    static void push(lua_State* L, T const& f)
    {
        apollo::push(L, make_function(f));
    }

    static unsigned n_conversion_steps(lua_State* L, int idx)
    {
        return fconverter::n_conversion_steps(L, idx);
    }

    static typename fconverter::type from_stack(lua_State* L, int idx)
    {
        return fconverter::from_stack(L, idx);
    }
};

} // namespace apollo

#endif // APOLLO_FUNCTION_HPP_INCLUDED
<commit_msg>function: Work around MSVC bug.<commit_after>#ifndef APOLLO_FUNCTION_HPP_INCLUDED
#define APOLLO_FUNCTION_HPP_INCLUDED APOLLO_FUNCTION_HPP_INCLUDED

#include <apollo/lapi.hpp>
#include <apollo/make_function.hpp>
#include <apollo/reference.hpp>
#include <apollo/stack_balance.hpp>

namespace apollo {

namespace detail {

std::type_info const& function_type(lua_State* L, int idx);

// function_converter //

template <typename F, typename Enable=void>
struct function_converter;

template <template<class> class FObj, typename R, typename... Args>
struct function_converter<FObj<R(Args...)>> {
    using type = FObj<R(Args...)>;

    static type from_stack(lua_State* L, int idx)
    {
        auto const& fty = function_type(L, idx);
        if (fty == typeid(type)) {
            stack_balance balance(L);
            BOOST_VERIFY(lua_getupvalue(L, idx, detail::fn_upval_fn));
            BOOST_ASSERT(lua_type(L, -1) == LUA_TUSERDATA); // Not light!
            return *static_cast<type*>(lua_touserdata(L, -1));
        }

        // Plain function pointer in Lua? Then construct from it.
        using plainfconv = function_converter<R(*)(Args...)>;
        if (fty == typeid(typename plainfconv::type))
            return plainfconv::from_stack(L, idx);

        // TODO?: optimization: Before falling back to the pcall lambda,
        // try boost::function and std::function.

        registry_reference luaFunction(L, idx, ref_mode::copy);
        return [luaFunction](Args... args) -> R {
            lua_State* L_ = luaFunction.L();
            stack_balance b(L_);
            luaFunction.push();
            // Use push_impl to allow empty Args.
            push_impl(L_, std::forward<Args>(args)...);
            pcall(L_, sizeof...(Args), 1);
            return apollo::from_stack<R>(L_, -1);
        };
    }

    static unsigned n_conversion_steps(lua_State* L, int idx)
    {
        if (lua_isfunction(L, idx))
            return 0;
        if (luaL_getmetafield(L, idx, "__call")) { // TODO: pcall
            lua_pop(L, 1);
            return 2;
        }
        return no_conversion;
    }
};

template <typename F>
struct function_converter<F, typename std::enable_if<
        detail::is_plain_function<F>::value ||
        std::is_member_function_pointer<F>::value>::type>
{
    using type = F;

    using is_light = is_light_function<F>;

    static F from_stack(lua_State* L, int idx)
    {
        stack_balance balance(L);
        BOOST_VERIFY(lua_getupvalue(L, idx, fn_upval_fn));
        BOOST_ASSERT(lua_isuserdata(L, -1));
        void* ud = lua_touserdata(L, -1);
        return from_stack_impl(ud, is_light());
    }

    static unsigned n_conversion_steps(lua_State* L, int idx)
    {
        return function_type(L, idx) == typeid(type) ? 0 : no_conversion;
    }

private:
    // Light function:
    static F from_stack_impl(void* ud, std::true_type)
    {
        return reinterpret_cast<light_function_holder<F>&>(ud).f;
    }

    // Non-light function:
    static F& from_stack_impl(void* ud, std::false_type)
    {
        return *static_cast<F*>(ud);
    }
};

} // namespace detail

// Function converter //
template<typename T>
struct converter<T, typename std::enable_if<
        detail::lua_type_id<T>::value == LUA_TFUNCTION>::type>
    : converter_base<T> {

private:
    // Work around a MSVC 12 (2013) bug, where
    // decltype(&fn_templateX<>) == decltype(fn_template<T>)
    // (another workaround would be to wrap the & in a function).
    using fn_t = typename std::conditional<
        std::is_function<T>::value, T*, T>::type;

    using fconverter = detail::function_converter<fn_t>;

public:
    static void push(lua_State* L, fn_t const& f)
    {
        apollo::push(L, make_function(f));
    }

    static unsigned n_conversion_steps(lua_State* L, int idx)
    {
        return fconverter::n_conversion_steps(L, idx);
    }

    static typename fconverter::type from_stack(lua_State* L, int idx)
    {
        return fconverter::from_stack(L, idx);
    }
};

} // namespace apollo

#endif // APOLLO_FUNCTION_HPP_INCLUDED
<|endoftext|>


<commit_before>#ifndef AUTOCHECK_VALUE_HPP
#define AUTOCHECK_VALUE_HPP

#include <cassert>

namespace autocheck {

  template <typename T>
  class value {
    private:
      enum {
        None,
        Static,
        Heap
      }    allocation = None;

      union {
        T* pointer = nullptr;
        T  object;
      };

    public:
      value() {}

      value(const value& copy) { *this = copy; }

      value& operator= (const value& rhs) {
        if (this == &rhs) return *this;

        if (rhs.allocation == Static) {
          construct(rhs.cref());
        } else if (rhs.allocation == Heap) {
          ptr(new T(rhs.cref()));
        }

        return *this;
      }

      value& operator= (const T& rhs) {
        construct(rhs);
        return *this;
      }

      value& operator= (T* rhs) {
        ptr(rhs);
        return *this;
      }

      bool empty() const { return allocation == None; }

      template <typename... Args>
      void construct(const Args&... args) {
        clear();
        T* p = new (&object) T(args...);
        assert(p == &object);
        allocation = Static;
      }

      const T* ptr() const {
        return (allocation == Heap) ? pointer : &object;
      }

      T* ptr() {
        return (allocation == Heap) ? pointer : &object;
      }

      void ptr(T* p) {
        clear();
        pointer    = p;
        allocation = p ? Heap : None;
      }

      T* operator-> ()             { return ptr(); }
      const T* operator-> () const { return ptr(); }

      T& ref()              { return *ptr(); }
      const T& ref()  const { return *ptr(); }
      const T& cref() const { return *ptr(); }

      operator T& ()             { return ref(); }
      operator const T& () const { return cref(); }

      void clear() {
        if (allocation == Heap) {
          delete ptr();
        } else if (allocation == Static) {
          ptr()->~T();
        }
        allocation = None;
      }

      ~value() { clear(); }

  };

  template <typename T>
  std::ostream& operator<< (std::ostream& out, const value<T>& v) {
    return out << v.cref();
  }

}

#endif

<commit_msg>With asserts turned off, value.hpp caused an unused variable warning.<commit_after>#ifndef AUTOCHECK_VALUE_HPP
#define AUTOCHECK_VALUE_HPP

#include <cassert>

namespace autocheck {

  template <typename T>
  class value {
    private:
      enum {
        None,
        Static,
        Heap
      }    allocation = None;

      union {
        T* pointer = nullptr;
        T  object;
      };

    public:
      value() {}

      value(const value& copy) { *this = copy; }

      value& operator= (const value& rhs) {
        if (this == &rhs) return *this;

        if (rhs.allocation == Static) {
          construct(rhs.cref());
        } else if (rhs.allocation == Heap) {
          ptr(new T(rhs.cref()));
        }

        return *this;
      }

      value& operator= (const T& rhs) {
        construct(rhs);
        return *this;
      }

      value& operator= (T* rhs) {
        ptr(rhs);
        return *this;
      }

      bool empty() const { return allocation == None; }

      template <typename... Args>
      void construct(const Args&... args) {
        clear();
        T* p = new (&object) T(args...);
        assert(p == &object);
        (void)p;
        allocation = Static;
      }

      const T* ptr() const {
        return (allocation == Heap) ? pointer : &object;
      }

      T* ptr() {
        return (allocation == Heap) ? pointer : &object;
      }

      void ptr(T* p) {
        clear();
        pointer    = p;
        allocation = p ? Heap : None;
      }

      T* operator-> ()             { return ptr(); }
      const T* operator-> () const { return ptr(); }

      T& ref()              { return *ptr(); }
      const T& ref()  const { return *ptr(); }
      const T& cref() const { return *ptr(); }

      operator T& ()             { return ref(); }
      operator const T& () const { return cref(); }

      void clear() {
        if (allocation == Heap) {
          delete ptr();
        } else if (allocation == Static) {
          ptr()->~T();
        }
        allocation = None;
      }

      ~value() { clear(); }

  };

  template <typename T>
  std::ostream& operator<< (std::ostream& out, const value<T>& v) {
    return out << v.cref();
  }

}

#endif

<|endoftext|>


<commit_before>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */

#include <string>
#include <sstream>
#include <regex>

#include "ConvolutionLayer.h"
#include "NonLinearityLayer.h"
#include "AdvancedMaxPoolingLayer.h"

#include "LayerFactory.h"

namespace Conv {
bool LayerFactory::IsValidDescriptor(std::string descriptor) {
  bool valid = std::regex_match(descriptor, std::regex("^[a-z]+(\\("
    "("
    "[a-z]+=[a-zA-Z0-9]+"
    "( [a-z]+=[a-zA-Z0-9]+)*"
    ")?"
    "\\))?$",std::regex::extended));
  return valid;
}

std::string LayerFactory::ExtractConfiguration(std::string descriptor) {
  std::smatch config_match;
  bool has_nonempty_configuration = std::regex_match(descriptor, config_match, std::regex("[a-z]+\\((.+)\\)",std::regex::extended));
  if(has_nonempty_configuration && config_match.size() == 2) {
    return config_match[1];
  } else {
    return "";
  }
}

std::string LayerFactory::ExtractLayerType(std::string descriptor) {
  std::smatch config_match;
  bool has_layertype = std::regex_match(descriptor, config_match, std::regex("([a-z]+)(\\(.*\\))?",std::regex::extended));
  if(has_layertype && config_match.size() > 1) {
    return config_match[1];
  } else {
    return "";
  }
}

#define CONV_LAYER_TYPE(ltype,lclass) else if (layertype.compare(ltype) == 0) { \
layer = new lclass (configuration) ; \
}

Layer* LayerFactory::ConstructLayer(std::string descriptor) {
  if (!IsValidDescriptor(descriptor))
    return nullptr;
  std::string configuration = ExtractConfiguration(descriptor);
  std::string layertype = ExtractLayerType(descriptor);

  Layer* layer = nullptr;
  if(layertype.length() == 0) {
    // Leave layer a nullptr
  }
  CONV_LAYER_TYPE("convolution", ConvolutionLayer)
  CONV_LAYER_TYPE("amaxpooling", AdvancedMaxPoolingLayer)
  CONV_LAYER_TYPE("tanh", TanhLayer)
  CONV_LAYER_TYPE("sigm", SigmoidLayer)
  CONV_LAYER_TYPE("relu", ReLULayer)

  return layer;
}

std::string LayerFactory::InjectSeed(std::string descriptor, unsigned int seed) {
  if(IsValidDescriptor(descriptor)) {
    std::string configuration = ExtractConfiguration(descriptor);
    std::string layertype = ExtractLayerType(descriptor);

    std::stringstream seed_ss;
    seed_ss << "seed=" << seed;

    bool already_has_seed = std::regex_match(configuration, std::regex(".*seed=[0-9]+.*", std::regex::extended));
    if(already_has_seed) {
      std::string new_descriptor = std::regex_replace(descriptor, std::regex("seed=([0-9])+", std::regex::extended), seed_ss.str());
      return new_descriptor;
    } else {
      std::stringstream new_descriptor_ss;
      new_descriptor_ss << layertype << "(";
      if(configuration.length() > 0) {
        new_descriptor_ss << configuration << " ";
      }
      new_descriptor_ss << seed_ss.str() << ")";
      std::string new_descriptor = new_descriptor_ss.str();
      return new_descriptor;
    }
  } else {
    return descriptor;
  }
}

}<commit_msg>LayerFactory: Added MaxPoolingLayer to registry<commit_after>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */

#include <string>
#include <sstream>
#include <regex>

#include "ConvolutionLayer.h"
#include "NonLinearityLayer.h"
#include "MaxPoolingLayer.h"
#include "AdvancedMaxPoolingLayer.h"

#include "LayerFactory.h"

namespace Conv {
bool LayerFactory::IsValidDescriptor(std::string descriptor) {
  bool valid = std::regex_match(descriptor, std::regex("^[a-z]+(\\("
    "("
    "[a-z]+=[a-zA-Z0-9]+"
    "( [a-z]+=[a-zA-Z0-9]+)*"
    ")?"
    "\\))?$",std::regex::extended));
  return valid;
}

std::string LayerFactory::ExtractConfiguration(std::string descriptor) {
  std::smatch config_match;
  bool has_nonempty_configuration = std::regex_match(descriptor, config_match, std::regex("[a-z]+\\((.+)\\)",std::regex::extended));
  if(has_nonempty_configuration && config_match.size() == 2) {
    return config_match[1];
  } else {
    return "";
  }
}

std::string LayerFactory::ExtractLayerType(std::string descriptor) {
  std::smatch config_match;
  bool has_layertype = std::regex_match(descriptor, config_match, std::regex("([a-z]+)(\\(.*\\))?",std::regex::extended));
  if(has_layertype && config_match.size() > 1) {
    return config_match[1];
  } else {
    return "";
  }
}

#define CONV_LAYER_TYPE(ltype,lclass) else if (layertype.compare(ltype) == 0) { \
layer = new lclass (configuration) ; \
}

Layer* LayerFactory::ConstructLayer(std::string descriptor) {
  if (!IsValidDescriptor(descriptor))
    return nullptr;
  std::string configuration = ExtractConfiguration(descriptor);
  std::string layertype = ExtractLayerType(descriptor);

  Layer* layer = nullptr;
  if(layertype.length() == 0) {
    // Leave layer a nullptr
  }
  CONV_LAYER_TYPE("convolution", ConvolutionLayer)
  CONV_LAYER_TYPE("maxpooling", MaxPoolingLayer)
  CONV_LAYER_TYPE("amaxpooling", AdvancedMaxPoolingLayer)
  CONV_LAYER_TYPE("tanh", TanhLayer)
  CONV_LAYER_TYPE("sigm", SigmoidLayer)
  CONV_LAYER_TYPE("relu", ReLULayer)

  return layer;
}

std::string LayerFactory::InjectSeed(std::string descriptor, unsigned int seed) {
  if(IsValidDescriptor(descriptor)) {
    std::string configuration = ExtractConfiguration(descriptor);
    std::string layertype = ExtractLayerType(descriptor);

    std::stringstream seed_ss;
    seed_ss << "seed=" << seed;

    bool already_has_seed = std::regex_match(configuration, std::regex(".*seed=[0-9]+.*", std::regex::extended));
    if(already_has_seed) {
      std::string new_descriptor = std::regex_replace(descriptor, std::regex("seed=([0-9])+", std::regex::extended), seed_ss.str());
      return new_descriptor;
    } else {
      std::stringstream new_descriptor_ss;
      new_descriptor_ss << layertype << "(";
      if(configuration.length() > 0) {
        new_descriptor_ss << configuration << " ";
      }
      new_descriptor_ss << seed_ss.str() << ")";
      std::string new_descriptor = new_descriptor_ss.str();
      return new_descriptor;
    }
  } else {
    return descriptor;
  }
}

}<|endoftext|>


<commit_before>/*
*******************************************************
        Parallel PLUQ quad recurisve with OpenMP
*******************************************************

g++ -D__FFLASFFPACK_HAVE_CBLAS -Wall -g -fopenmp -O3 -march=native -mavx -I/home/sultan/soft/fflas-ffpack/ -I/usr/local/soft/givaro-3.7.1/include  test-ppluq.C -L/home/pernet/Logiciels/ATLAS_1TH/lib -lcblas -latlas -L/usr/local/soft/givaro-3.7.1/lib -lgivaro -lm -lrt -Wl,-rpath -Wl,/usr/local/soft/givaro-3.7.1/lib  -o test-ppluq
*/

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <iomanip>
//#include "omp.h"

#define __FFLASFFPACK_USE_OPENMP

#define __FFLAS__TRSM_READONLY
#define __PFTRSM_FOR_PLUQ
#include "fflas-ffpack/utils/Matio.h"
//#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/ffpack/ffpack.h"
#include "fflas-ffpack/fflas-ffpack.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "sys/time.h"

//#define BASECASE_K 256

//#include "fflas-ffpack/ffpack/parallel.h"

using namespace std;
using namespace FFLAS;
using namespace FFPACK;
#ifndef MODULO
#define MODULO 1
#endif

#if(MODULO==1)
typedef FFPACK::Modular<double> Field;
#else
typedef FFPACK::UnparametricField<double> Field;
#endif

#ifndef DEBUG
#define DEBUG 1
#endif

#ifndef SEQ
#define SEQ 1
#endif

void verification_PLUQ(const Field & F, typename Field::Element * B, typename Field::Element * A,
		       size_t * P, size_t * Q, size_t m, size_t n, size_t R)
{

  Field::Element * X = FFLAS::fflas_new<Field::Element>(m*n);
  Field::Element * L, *U;
  L = FFLAS::fflas_new<Field::Element>(m*R);
  U = FFLAS::fflas_new<Field::Element>(R*n);

  for (size_t i=0; i<m*R; ++i)
    F.init(L[i], 0.0);

  for (size_t i=0; i<m*R; ++i)
    F.init(U[i], 0.0);

  for (size_t i=0; i<m*n; ++i)
    F.init(X[i], 0.0);

  Field::Element zero,one;
  F.init(zero,0.0);
  F.init(one,1.0);
  for (size_t i=0; i<R; ++i){
    for (size_t j=0; j<i; ++j)
      F.assign ( *(U + i*n + j), zero);
    for (size_t j=i; j<n; ++j)
      F.assign (*(U + i*n + j), *(A+ i*n+j));
  }
  for ( size_t j=0; j<R; ++j ){
    for (size_t i=0; i<=j; ++i )
      F.assign( *(L+i*R+j), zero);
    F.assign(*(L+j*R+j), one);
    for (size_t i=j+1; i<m; i++)
      F.assign( *(L + i*R+j), *(A+i*n+j));
  }

  FFPACK::applyP( F, FFLAS::FflasLeft, FFLAS::FflasTrans, R,0,m, L, R, P);

  FFPACK::applyP (F, FFLAS::FflasRight, FFLAS::FflasNoTrans, R,0,n, U, n, Q);
  FFLAS::fgemm (F, FFLAS::FflasNoTrans, FFLAS::FflasNoTrans, m,n,R,
		1.0, L,R, U,n, 0.0, X,n);
  bool fail = false;
  for (size_t i=0; i<m; ++i)
    for (size_t j=0; j<n; ++j)
      if (!F.areEqual (*(B+i*n+j), *(X+i*n+j))){
	std::cerr << " B["<<i<<","<<j<<"] = " << (*(B+i*n+j))
		  << " X["<<i<<","<<j<<"] = " << (*(X+i*n+j))
		  << std::endl;
	fail=true;
      }

  if (fail)
    std::cerr<<"FAIL"<<std::endl;

  else
    std::cerr<<"PASS"<<std::endl;
  FFLAS::fflas_delete( U);
  FFLAS::fflas_delete( L);
  FFLAS::fflas_delete( X);
}

int main(int argc, char** argv)
{

    int p, n, m, nbf;

	if (argc > 6){
		std::cerr<<"usage : PLUQ-rec-omp <p> <m> <n> <i> <file>"<<std::endl
//		std::cerr<<"usage : PLUQ-rec-omp <m> <n> <p> <r> <i>"<<std::endl
		    <<std::endl;
		exit(-1);
	}

	p = (argc>1 ? atoi( argv[1] ) : 1009);

	m = (argc>2 ? atoi( argv[2] ) : 1024);
	n = (argc>3 ? atoi( argv[3] ) : 1024);
	// r = atoi( argv[4] );
	nbf = (argc>4 ? atoi( argv[4] ) : 1);

	//	size_t lda = n;

		// random seed
	// ifstream f("/dev/urandom");
	// size_t seed1, seed2, seed3,seed4;
	// f.read(reinterpret_cast<char*>(&seed1), sizeof(seed1));
	// f.read(reinterpret_cast<char*>(&seed2), sizeof(seed2));
	// f.read(reinterpret_cast<char*>(&seed3), sizeof(seed3));
	// f.read(reinterpret_cast<char*>(&seed4), sizeof(seed4));

//     seed1=10;seed2=12;
//     seed3=13;seed4=14;

        enum FFLAS::FFLAS_DIAG diag = FFLAS::FflasNonUnit;
        size_t R;
#if(MODULO==1)
	typedef FFPACK::Modular<double> Field;
#else
	typedef FFPACK::UnparametricField<double> Field;
#endif

	const Field F((double)p);
	// Field::RandIter G(F, seed1);

	Field::Element alpha, beta;
	F.init(alpha,1.0);
	F.init(beta,0.0);
	// Field::Element * U = FFLAS::fflas_new<Field::Element>(n*n);

	typename Field::Element* Acop;
    if (argc > 5) {
        Acop = read_field(F,argv[5],&m,&n);
    } else {
        Field::RandIter G(F);
        Acop = FFLAS::fflas_new<Field::Element>(m*n);
        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                G.random (*(Acop+i*n+j));
    }

// FFLAS::fflas_new<Field::Element>(n*m);
	Field::Element* A = FFLAS::fflas_new<Field::Element>(n*m);
#if(DEBUG==1)
	Field::Element* Adebug = FFLAS::fflas_new<Field::Element>(n*m);
#endif
	// std::vector<size_t> Index_P(r);

	// U = construct_U(F,G, n, r, Index_P, seed4, seed3);
	// A = construct_L(F,G, m, r, Index_P, seed2);
	// M_randgen(F, A, U, r, m, n);
	// size_t taille=m*n;
	// for(size_t i=0; i<taille;++i) U[i]=A[i];

	struct timespec t0, t1;// tt0, tt1;
	double delay, avrg;//, avrgg;
	double t_total=0;

    size_t maxP, maxQ;
    maxP = m;
    maxQ = n;

    size_t *P = FFLAS::fflas_new<size_t>(maxP);
    size_t *Q = FFLAS::fflas_new<size_t>(maxQ);

    PAR_FOR(size_t i=0; i<(size_t)m; ++i)
        for (size_t j=0; j<(size_t)n; ++j) {
            *(A+i*n+j) = *(Acop+i*n+j) ;
#if(DEBUG==1)
            *(Adebug+i*n+j) = *(Acop+i*n+j) ;
#endif
        }

    for ( int i=0;i<nbf+1;i++){
        for (size_t j=0;j<maxP;j++)
            P[j]=0;
        for (size_t j=0;j<maxQ;j++)
            Q[j]=0;

        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                *(A+i*n+j) = *(Acop+i*n+j) ;

	    clock_gettime(CLOCK_REALTIME, &t0);
	    PAR_REGION{
            R = pPLUQ(F, diag, m, n, A, n, P, Q);// Parallel PLUQ
	    }
	    clock_gettime(CLOCK_REALTIME, &t1);
	    delay = (double)(t1.tv_sec-t0.tv_sec)+(double)(t1.tv_nsec-t0.tv_nsec)/1000000000;

	    if(i)
            t_total +=delay;

    }
    avrg = t_total/nbf;
    std::cerr << "MODULO: " << (MODULO?p:0) << std::endl;

    PAR_REGION{
        std::cerr<<"Parallel --- m: "<<m<<" , n: " << n << " , r: " <<R<<" "
                 <<avrg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrg))<<" "
                //#ifdef  __FFLASFFPACK_USE_OPENMP
                 <<NUM_THREADS<<endl;
            //#else
    }
        //<<endl;
        //#endi

        //	std::cout<<typeid(A).name()<<endl;
#if(DEBUG==1)
	cout<<"check equality A == PLUQ ?"<<endl;
    verification_PLUQ(F,Adebug,A,P,Q,m,n,R);
    FFLAS::fflas_delete( Adebug);
#endif
#if(SEQ==1)
	struct timespec  tt0, tt1;
	double avrgg;
	//call sequential PLUQ
	size_t * PP = FFLAS::fflas_new<size_t>(maxP);
	size_t * QQ = FFLAS::fflas_new<size_t>(maxQ);
	for (size_t j=0;j<maxP;j++)
	  PP[j]=0;
	for (size_t j=0;j<maxQ;j++)
	  QQ[j]=0;
	clock_gettime(CLOCK_REALTIME, &tt0);
	size_t R2 = PLUQ(F, diag, m, n, Acop, n, PP, QQ);
	clock_gettime(CLOCK_REALTIME, &tt1);
        FFLAS::fflas_delete( Acop);
	avrgg = (double)(tt1.tv_sec-tt0.tv_sec)+(double)(tt1.tv_nsec-tt0.tv_nsec)/1000000000;
	//verification
	std::cerr<<"Sequential : "<<m<<" "<<R2<<" "
                 <<avrgg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrgg))<<endl;
#endif

        FFLAS::fflas_delete( A);
	return 0;
}
<commit_msg>field defined twice<commit_after>/*
*******************************************************
        Parallel PLUQ quad recurisve with OpenMP
*******************************************************

g++ -D__FFLASFFPACK_HAVE_CBLAS -Wall -g -fopenmp -O3 -march=native -mavx -I/home/sultan/soft/fflas-ffpack/ -I/usr/local/soft/givaro-3.7.1/include  test-ppluq.C -L/home/pernet/Logiciels/ATLAS_1TH/lib -lcblas -latlas -L/usr/local/soft/givaro-3.7.1/lib -lgivaro -lm -lrt -Wl,-rpath -Wl,/usr/local/soft/givaro-3.7.1/lib  -o test-ppluq
*/

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <iomanip>
//#include "omp.h"

#define __FFLASFFPACK_USE_OPENMP

#define __FFLAS__TRSM_READONLY
#define __PFTRSM_FOR_PLUQ
#include "fflas-ffpack/utils/Matio.h"
//#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/ffpack/ffpack.h"
#include "fflas-ffpack/fflas-ffpack.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "sys/time.h"

//#define BASECASE_K 256

//#include "fflas-ffpack/ffpack/parallel.h"

using namespace std;
using namespace FFLAS;
using namespace FFPACK;
#ifndef MODULO
#define MODULO 1
#endif

#if(MODULO==1)
typedef FFPACK::Modular<double> Field;
#else
typedef FFPACK::UnparametricField<double> Field;
#endif

#ifndef DEBUG
#define DEBUG 1
#endif

#ifndef SEQ
#define SEQ 1
#endif

void verification_PLUQ(const Field & F, typename Field::Element * B, typename Field::Element * A,
		       size_t * P, size_t * Q, size_t m, size_t n, size_t R)
{

  Field::Element * X = FFLAS::fflas_new<Field::Element>(m*n);
  Field::Element * L, *U;
  L = FFLAS::fflas_new<Field::Element>(m*R);
  U = FFLAS::fflas_new<Field::Element>(R*n);

  for (size_t i=0; i<m*R; ++i)
    F.init(L[i], 0.0);

  for (size_t i=0; i<m*R; ++i)
    F.init(U[i], 0.0);

  for (size_t i=0; i<m*n; ++i)
    F.init(X[i], 0.0);

  Field::Element zero,one;
  F.init(zero,0.0);
  F.init(one,1.0);
  for (size_t i=0; i<R; ++i){
    for (size_t j=0; j<i; ++j)
      F.assign ( *(U + i*n + j), zero);
    for (size_t j=i; j<n; ++j)
      F.assign (*(U + i*n + j), *(A+ i*n+j));
  }
  for ( size_t j=0; j<R; ++j ){
    for (size_t i=0; i<=j; ++i )
      F.assign( *(L+i*R+j), zero);
    F.assign(*(L+j*R+j), one);
    for (size_t i=j+1; i<m; i++)
      F.assign( *(L + i*R+j), *(A+i*n+j));
  }

  FFPACK::applyP( F, FFLAS::FflasLeft, FFLAS::FflasTrans, R,0,m, L, R, P);

  FFPACK::applyP (F, FFLAS::FflasRight, FFLAS::FflasNoTrans, R,0,n, U, n, Q);
  FFLAS::fgemm (F, FFLAS::FflasNoTrans, FFLAS::FflasNoTrans, m,n,R,
		1.0, L,R, U,n, 0.0, X,n);
  bool fail = false;
  for (size_t i=0; i<m; ++i)
    for (size_t j=0; j<n; ++j)
      if (!F.areEqual (*(B+i*n+j), *(X+i*n+j))){
	std::cerr << " B["<<i<<","<<j<<"] = " << (*(B+i*n+j))
		  << " X["<<i<<","<<j<<"] = " << (*(X+i*n+j))
		  << std::endl;
	fail=true;
      }

  if (fail)
    std::cerr<<"FAIL"<<std::endl;

  else
    std::cerr<<"PASS"<<std::endl;
  FFLAS::fflas_delete( U);
  FFLAS::fflas_delete( L);
  FFLAS::fflas_delete( X);
}

int main(int argc, char** argv)
{

    int p, n, m, nbf;

	if (argc > 6){
		std::cerr<<"usage : PLUQ-rec-omp <p> <m> <n> <i> <file>"<<std::endl
//		std::cerr<<"usage : PLUQ-rec-omp <m> <n> <p> <r> <i>"<<std::endl
		    <<std::endl;
		exit(-1);
	}

	p = (argc>1 ? atoi( argv[1] ) : 1009);

	m = (argc>2 ? atoi( argv[2] ) : 1024);
	n = (argc>3 ? atoi( argv[3] ) : 1024);
	// r = atoi( argv[4] );
	nbf = (argc>4 ? atoi( argv[4] ) : 1);

	//	size_t lda = n;

		// random seed
	// ifstream f("/dev/urandom");
	// size_t seed1, seed2, seed3,seed4;
	// f.read(reinterpret_cast<char*>(&seed1), sizeof(seed1));
	// f.read(reinterpret_cast<char*>(&seed2), sizeof(seed2));
	// f.read(reinterpret_cast<char*>(&seed3), sizeof(seed3));
	// f.read(reinterpret_cast<char*>(&seed4), sizeof(seed4));

//     seed1=10;seed2=12;
//     seed3=13;seed4=14;

        enum FFLAS::FFLAS_DIAG diag = FFLAS::FflasNonUnit;
        size_t R;

	const Field F((double)p);
	// Field::RandIter G(F, seed1);

	Field::Element alpha, beta;
	F.init(alpha,1.0);
	F.init(beta,0.0);
	// Field::Element * U = FFLAS::fflas_new<Field::Element>(n*n);

	typename Field::Element* Acop;
    if (argc > 5) {
        Acop = read_field(F,argv[5],&m,&n);
    } else {
        Field::RandIter G(F);
        Acop = FFLAS::fflas_new<Field::Element>(m*n);
        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                G.random (*(Acop+i*n+j));
    }

// FFLAS::fflas_new<Field::Element>(n*m);
	Field::Element* A = FFLAS::fflas_new<Field::Element>(n*m);
#if(DEBUG==1)
	Field::Element* Adebug = FFLAS::fflas_new<Field::Element>(n*m);
#endif
	// std::vector<size_t> Index_P(r);

	// U = construct_U(F,G, n, r, Index_P, seed4, seed3);
	// A = construct_L(F,G, m, r, Index_P, seed2);
	// M_randgen(F, A, U, r, m, n);
	// size_t taille=m*n;
	// for(size_t i=0; i<taille;++i) U[i]=A[i];

	struct timespec t0, t1;// tt0, tt1;
	double delay, avrg;//, avrgg;
	double t_total=0;

    size_t maxP, maxQ;
    maxP = m;
    maxQ = n;

    size_t *P = FFLAS::fflas_new<size_t>(maxP);
    size_t *Q = FFLAS::fflas_new<size_t>(maxQ);

    PAR_FOR(size_t i=0; i<(size_t)m; ++i)
        for (size_t j=0; j<(size_t)n; ++j) {
            *(A+i*n+j) = *(Acop+i*n+j) ;
#if(DEBUG==1)
            *(Adebug+i*n+j) = *(Acop+i*n+j) ;
#endif
        }

    for ( int i=0;i<nbf+1;i++){
        for (size_t j=0;j<maxP;j++)
            P[j]=0;
        for (size_t j=0;j<maxQ;j++)
            Q[j]=0;

        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                *(A+i*n+j) = *(Acop+i*n+j) ;

	    clock_gettime(CLOCK_REALTIME, &t0);
	    PAR_REGION{
            R = pPLUQ(F, diag, m, n, A, n, P, Q);// Parallel PLUQ
	    }
	    clock_gettime(CLOCK_REALTIME, &t1);
	    delay = (double)(t1.tv_sec-t0.tv_sec)+(double)(t1.tv_nsec-t0.tv_nsec)/1000000000;

	    if(i)
            t_total +=delay;

    }
    avrg = t_total/nbf;
    std::cerr << "MODULO: " << (MODULO?p:0) << std::endl;

    PAR_REGION{
        std::cerr<<"Parallel --- m: "<<m<<" , n: " << n << " , r: " <<R<<" "
                 <<avrg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrg))<<" "
                //#ifdef  __FFLASFFPACK_USE_OPENMP
                 <<NUM_THREADS<<endl;
            //#else
    }
        //<<endl;
        //#endi

        //	std::cout<<typeid(A).name()<<endl;
#if(DEBUG==1)
	cout<<"check equality A == PLUQ ?"<<endl;
    verification_PLUQ(F,Adebug,A,P,Q,m,n,R);
    FFLAS::fflas_delete( Adebug);
#endif
#if(SEQ==1)
	struct timespec  tt0, tt1;
	double avrgg;
	//call sequential PLUQ
	size_t * PP = FFLAS::fflas_new<size_t>(maxP);
	size_t * QQ = FFLAS::fflas_new<size_t>(maxQ);
	for (size_t j=0;j<maxP;j++)
	  PP[j]=0;
	for (size_t j=0;j<maxQ;j++)
	  QQ[j]=0;
	clock_gettime(CLOCK_REALTIME, &tt0);
	size_t R2 = PLUQ(F, diag, m, n, Acop, n, PP, QQ);
	clock_gettime(CLOCK_REALTIME, &tt1);
        FFLAS::fflas_delete( Acop);
	avrgg = (double)(tt1.tv_sec-tt0.tv_sec)+(double)(tt1.tv_nsec-tt0.tv_nsec)/1000000000;
	//verification
	std::cerr<<"Sequential : "<<m<<" "<<R2<<" "
                 <<avrgg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrgg))<<endl;
#endif

        FFLAS::fflas_delete( A);
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>added pause state on lost focus<commit_after><|endoftext|>


<commit_before>//===-- sanitizer_thread_registry_test.cc ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of shared sanitizer runtime.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_thread_registry.h"

#include "sanitizer_pthread_wrappers.h"

#include "gtest/gtest.h"

#include <vector>

namespace __sanitizer {

static BlockingMutex tctx_allocator_lock(LINKER_INITIALIZED);
static LowLevelAllocator tctx_allocator;

template<typename TCTX>
static ThreadContextBase *GetThreadContext(u32 tid) {
  BlockingMutexLock l(&tctx_allocator_lock);
  return new(tctx_allocator) TCTX(tid);
}

static const u32 kMaxRegistryThreads = 1000;
static const u32 kRegistryQuarantine = 2;

static void CheckThreadQuantity(ThreadRegistry *registry, uptr exp_total,
                                uptr exp_running, uptr exp_alive) {
  uptr total, running, alive;
  registry->GetNumberOfThreads(&total, &running, &alive);
  EXPECT_EQ(exp_total, total);
  EXPECT_EQ(exp_running, running);
  EXPECT_EQ(exp_alive, alive);
}

static bool is_detached(u32 tid) {
  return (tid % 2 == 0);
}

static uptr get_uid(u32 tid) {
  return tid * 2;
}

static bool HasName(ThreadContextBase *tctx, void *arg) {
  char *name = (char*)arg;
  return (0 == internal_strcmp(tctx->name, name));
}

static bool HasUid(ThreadContextBase *tctx, void *arg) {
  uptr uid = (uptr)arg;
  return (tctx->user_id == uid);
}

static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) {
  bool *arr = (bool*)arg;
  arr[tctx->tid] = true;
}

static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0));
  registry->StartThread(0, 0, 0);
  // Create a bunch of threads.
  for (u32 i = 1; i <= 10; i++) {
    EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  CheckThreadQuantity(registry, 11, 1, 11);
  // Start some of them.
  for (u32 i = 1; i <= 5; i++) {
    registry->StartThread(i, 0, 0);
  }
  CheckThreadQuantity(registry, 11, 6, 11);
  // Finish, create and start more threads.
  for (u32 i = 1; i <= 5; i++) {
    registry->FinishThread(i);
    if (!is_detached(i))
      registry->JoinThread(i, 0);
  }
  for (u32 i = 6; i <= 10; i++) {
    registry->StartThread(i, 0, 0);
  }
  std::vector<u32> new_tids;
  for (u32 i = 11; i <= 15; i++) {
    new_tids.push_back(
        registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  ASSERT_LE(kRegistryQuarantine, 5U);
  u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine  : 0);
  CheckThreadQuantity(registry, exp_total, 6, 11);
  // Test SetThreadName and FindThread.
  registry->SetThreadName(6, "six");
  registry->SetThreadName(7, "seven");
  EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven"));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasName, (void*)"none"));
  EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0)));
  EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10)));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasUid, (void*)0x1234));
  // Detach and finish and join remaining threads.
  for (u32 i = 6; i <= 10; i++) {
    registry->DetachThread(i, 0);
    registry->FinishThread(i);
  }
  for (u32 i = 0; i < new_tids.size(); i++) {
    u32 tid = new_tids[i];
    registry->StartThread(tid, 0, 0);
    registry->DetachThread(tid, 0);
    registry->FinishThread(tid);
  }
  CheckThreadQuantity(registry, exp_total, 1, 1);
  // Test methods that require the caller to hold a ThreadRegistryLock.
  bool has_tid[16];
  internal_memset(&has_tid[0], 0, sizeof(has_tid));
  {
    ThreadRegistryLock l(registry);
    registry->RunCallbackForEachThreadLocked(MarkUidAsPresent, &has_tid[0]);
  }
  for (u32 i = 0; i < exp_total; i++) {
    EXPECT_TRUE(has_tid[i]);
  }
  {
    ThreadRegistryLock l(registry);
    registry->CheckLocked();
    ThreadContextBase *main_thread = registry->GetThreadLocked(0);
    EXPECT_EQ(main_thread, registry->FindThreadContextLocked(
        HasUid, (void*)get_uid(0)));
  }
  EXPECT_EQ(11U, registry->GetMaxAliveThreads());
}

TEST(SanitizerCommon, ThreadRegistryTest) {
  ThreadRegistry quarantine_registry(GetThreadContext<ThreadContextBase>,
                                     kMaxRegistryThreads,
                                     kRegistryQuarantine);
  TestRegistry(&quarantine_registry, true);

  ThreadRegistry no_quarantine_registry(GetThreadContext<ThreadContextBase>,
                                        kMaxRegistryThreads,
                                        kMaxRegistryThreads);
  TestRegistry(&no_quarantine_registry, false);
}

static const int kThreadsPerShard = 20;
static const int kNumShards = 25;

static int num_created[kNumShards + 1];
static int num_started[kNumShards + 1];
static int num_joined[kNumShards + 1];

namespace {

struct RunThreadArgs {
  ThreadRegistry *registry;
  uptr shard;  // started from 1.
};

class TestThreadContext : public ThreadContextBase {
 public:
  explicit TestThreadContext(int tid) : ThreadContextBase(tid) {}
  void OnJoined(void *arg) {
    uptr shard = (uptr)arg;
    num_joined[shard]++;
  }
  void OnStarted(void *arg) {
    uptr shard = (uptr)arg;
    num_started[shard]++;
  }
  void OnCreated(void *arg) {
    uptr shard = (uptr)arg;
    num_created[shard]++;
  }
};

}  // namespace

void *RunThread(void *arg) {
  RunThreadArgs *args = static_cast<RunThreadArgs*>(arg);
  std::vector<int> tids;
  for (int i = 0; i < kThreadsPerShard; i++)
    tids.push_back(
        args->registry->CreateThread(0, false, 0, (void*)args->shard));
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->StartThread(tids[i], 0, (void*)args->shard);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->FinishThread(tids[i]);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->JoinThread(tids[i], (void*)args->shard);
  return 0;
}

static void ThreadedTestRegistry(ThreadRegistry *registry) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0));
  registry->StartThread(0, 0, 0);
  pthread_t threads[kNumShards];
  RunThreadArgs args[kNumShards];
  for (int i = 0; i < kNumShards; i++) {
    args[i].registry = registry;
    args[i].shard = i + 1;
    PTHREAD_CREATE(&threads[i], 0, RunThread, &args[i]);
  }
  for (int i = 0; i < kNumShards; i++) {
    PTHREAD_JOIN(threads[i], 0);
  }
  // Check that each thread created/started/joined correct amount
  // of "threads" in thread_registry.
  EXPECT_EQ(1, num_created[0]);
  EXPECT_EQ(1, num_started[0]);
  EXPECT_EQ(0, num_joined[0]);
  for (int i = 1; i <= kNumShards; i++) {
    EXPECT_EQ(kThreadsPerShard, num_created[i]);
    EXPECT_EQ(kThreadsPerShard, num_started[i]);
    EXPECT_EQ(kThreadsPerShard, num_joined[i]);
  }
}

TEST(SanitizerCommon, ThreadRegistryThreadedTest) {
  memset(&num_created, 0, sizeof(num_created));
  memset(&num_started, 0, sizeof(num_created));
  memset(&num_joined, 0, sizeof(num_created));

  ThreadRegistry registry(GetThreadContext<TestThreadContext>,
                          kThreadsPerShard * kNumShards + 1, 10);
  ThreadedTestRegistry(&registry);
}

}  // namespace __sanitizer
<commit_msg>Fixup of r293882:  Forgot to update sanitizer_thread_registry.test.cc<commit_after>//===-- sanitizer_thread_registry_test.cc ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of shared sanitizer runtime.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_thread_registry.h"

#include "sanitizer_pthread_wrappers.h"

#include "gtest/gtest.h"

#include <vector>

namespace __sanitizer {

static BlockingMutex tctx_allocator_lock(LINKER_INITIALIZED);
static LowLevelAllocator tctx_allocator;

template<typename TCTX>
static ThreadContextBase *GetThreadContext(u32 tid) {
  BlockingMutexLock l(&tctx_allocator_lock);
  return new(tctx_allocator) TCTX(tid);
}

static const u32 kMaxRegistryThreads = 1000;
static const u32 kRegistryQuarantine = 2;

static void CheckThreadQuantity(ThreadRegistry *registry, uptr exp_total,
                                uptr exp_running, uptr exp_alive) {
  uptr total, running, alive;
  registry->GetNumberOfThreads(&total, &running, &alive);
  EXPECT_EQ(exp_total, total);
  EXPECT_EQ(exp_running, running);
  EXPECT_EQ(exp_alive, alive);
}

static bool is_detached(u32 tid) {
  return (tid % 2 == 0);
}

static uptr get_uid(u32 tid) {
  return tid * 2;
}

static bool HasName(ThreadContextBase *tctx, void *arg) {
  char *name = (char*)arg;
  return (0 == internal_strcmp(tctx->name, name));
}

static bool HasUid(ThreadContextBase *tctx, void *arg) {
  uptr uid = (uptr)arg;
  return (tctx->user_id == uid);
}

static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) {
  bool *arr = (bool*)arg;
  arr[tctx->tid] = true;
}

static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0));
  registry->StartThread(0, 0, false, 0);
  // Create a bunch of threads.
  for (u32 i = 1; i <= 10; i++) {
    EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  CheckThreadQuantity(registry, 11, 1, 11);
  // Start some of them.
  for (u32 i = 1; i <= 5; i++) {
    registry->StartThread(i, 0, false, 0);
  }
  CheckThreadQuantity(registry, 11, 6, 11);
  // Finish, create and start more threads.
  for (u32 i = 1; i <= 5; i++) {
    registry->FinishThread(i);
    if (!is_detached(i))
      registry->JoinThread(i, 0);
  }
  for (u32 i = 6; i <= 10; i++) {
    registry->StartThread(i, 0, false, 0);
  }
  std::vector<u32> new_tids;
  for (u32 i = 11; i <= 15; i++) {
    new_tids.push_back(
        registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  ASSERT_LE(kRegistryQuarantine, 5U);
  u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine  : 0);
  CheckThreadQuantity(registry, exp_total, 6, 11);
  // Test SetThreadName and FindThread.
  registry->SetThreadName(6, "six");
  registry->SetThreadName(7, "seven");
  EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven"));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasName, (void*)"none"));
  EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0)));
  EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10)));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasUid, (void*)0x1234));
  // Detach and finish and join remaining threads.
  for (u32 i = 6; i <= 10; i++) {
    registry->DetachThread(i, 0);
    registry->FinishThread(i);
  }
  for (u32 i = 0; i < new_tids.size(); i++) {
    u32 tid = new_tids[i];
    registry->StartThread(tid, 0, false, 0);
    registry->DetachThread(tid, 0);
    registry->FinishThread(tid);
  }
  CheckThreadQuantity(registry, exp_total, 1, 1);
  // Test methods that require the caller to hold a ThreadRegistryLock.
  bool has_tid[16];
  internal_memset(&has_tid[0], 0, sizeof(has_tid));
  {
    ThreadRegistryLock l(registry);
    registry->RunCallbackForEachThreadLocked(MarkUidAsPresent, &has_tid[0]);
  }
  for (u32 i = 0; i < exp_total; i++) {
    EXPECT_TRUE(has_tid[i]);
  }
  {
    ThreadRegistryLock l(registry);
    registry->CheckLocked();
    ThreadContextBase *main_thread = registry->GetThreadLocked(0);
    EXPECT_EQ(main_thread, registry->FindThreadContextLocked(
        HasUid, (void*)get_uid(0)));
  }
  EXPECT_EQ(11U, registry->GetMaxAliveThreads());
}

TEST(SanitizerCommon, ThreadRegistryTest) {
  ThreadRegistry quarantine_registry(GetThreadContext<ThreadContextBase>,
                                     kMaxRegistryThreads,
                                     kRegistryQuarantine);
  TestRegistry(&quarantine_registry, true);

  ThreadRegistry no_quarantine_registry(GetThreadContext<ThreadContextBase>,
                                        kMaxRegistryThreads,
                                        kMaxRegistryThreads);
  TestRegistry(&no_quarantine_registry, false);
}

static const int kThreadsPerShard = 20;
static const int kNumShards = 25;

static int num_created[kNumShards + 1];
static int num_started[kNumShards + 1];
static int num_joined[kNumShards + 1];

namespace {

struct RunThreadArgs {
  ThreadRegistry *registry;
  uptr shard;  // started from 1.
};

class TestThreadContext : public ThreadContextBase {
 public:
  explicit TestThreadContext(int tid) : ThreadContextBase(tid) {}
  void OnJoined(void *arg) {
    uptr shard = (uptr)arg;
    num_joined[shard]++;
  }
  void OnStarted(void *arg) {
    uptr shard = (uptr)arg;
    num_started[shard]++;
  }
  void OnCreated(void *arg) {
    uptr shard = (uptr)arg;
    num_created[shard]++;
  }
};

}  // namespace

void *RunThread(void *arg) {
  RunThreadArgs *args = static_cast<RunThreadArgs*>(arg);
  std::vector<int> tids;
  for (int i = 0; i < kThreadsPerShard; i++)
    tids.push_back(
        args->registry->CreateThread(0, false, 0, (void*)args->shard));
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->StartThread(tids[i], 0, false, (void*)args->shard);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->FinishThread(tids[i]);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->JoinThread(tids[i], (void*)args->shard);
  return 0;
}

static void ThreadedTestRegistry(ThreadRegistry *registry) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0));
  registry->StartThread(0, 0, false, 0);
  pthread_t threads[kNumShards];
  RunThreadArgs args[kNumShards];
  for (int i = 0; i < kNumShards; i++) {
    args[i].registry = registry;
    args[i].shard = i + 1;
    PTHREAD_CREATE(&threads[i], 0, RunThread, &args[i]);
  }
  for (int i = 0; i < kNumShards; i++) {
    PTHREAD_JOIN(threads[i], 0);
  }
  // Check that each thread created/started/joined correct amount
  // of "threads" in thread_registry.
  EXPECT_EQ(1, num_created[0]);
  EXPECT_EQ(1, num_started[0]);
  EXPECT_EQ(0, num_joined[0]);
  for (int i = 1; i <= kNumShards; i++) {
    EXPECT_EQ(kThreadsPerShard, num_created[i]);
    EXPECT_EQ(kThreadsPerShard, num_started[i]);
    EXPECT_EQ(kThreadsPerShard, num_joined[i]);
  }
}

TEST(SanitizerCommon, ThreadRegistryThreadedTest) {
  memset(&num_created, 0, sizeof(num_created));
  memset(&num_started, 0, sizeof(num_created));
  memset(&num_joined, 0, sizeof(num_created));

  ThreadRegistry registry(GetThreadContext<TestThreadContext>,
                          kThreadsPerShard * kNumShards + 1, 10);
  ThreadedTestRegistry(&registry);
}

}  // namespace __sanitizer
<|endoftext|>


<commit_before>//==============================================================================
// Compiler scanner class
//==============================================================================

#include "compilerscanner.h"

//==============================================================================

namespace OpenCOR {
namespace Compiler {

//==============================================================================

static const QChar Underscore          = QChar('_');
static const QChar OpeningBracket      = QChar('(');
static const QChar ClosingBracket      = QChar(')');
static const QChar OpeningCurlyBracket = QChar('{');
static const QChar ClosingCurlyBracket = QChar('}');

//==============================================================================

CompilerScannerToken::CompilerScannerToken(const int pLine, const int pColumn) :
    mLine(pLine),
    mColumn(pColumn),
    mSymbol(Eof),
    mString(QString())
{
}

//==============================================================================

int CompilerScannerToken::line() const
{
    // Return the token's line

    return mLine;
}

//==============================================================================

int CompilerScannerToken::column() const
{
    // Return the token's column

    return mColumn;
}

//==============================================================================

CompilerScannerToken::Symbol CompilerScannerToken::symbol() const
{
    // Return the token's symbol

    return mSymbol;
}

//==============================================================================

QString CompilerScannerToken::symbolAsString() const
{
    // Return the token's symbol as a string

    switch (mSymbol) {
    case Void:
        return "Void";
    case Double:
        return "Double";
    case OpeningBracket:
        return "OpeningBracket";
    case ClosingBracket:
        return "ClosingBracket";
    case OpeningCurlyBracket:
        return "OpeningCurlyBracket";
    case ClosingCurlyBracket:
        return "ClosingCurlyBracket";
    case Unknown:
        return "Unknown";
    case Identifier:
        return "Identifier";
    case Eof:
        return "Eof";
    default:
        return "???";
    }
}

//==============================================================================

void CompilerScannerToken::setSymbol(const Symbol &pSymbol)
{
    // Set the token's symbol

    mSymbol = pSymbol;
}

//==============================================================================

QString CompilerScannerToken::string() const
{
    // Return the token's string

    return mString;
}

//==============================================================================

void CompilerScannerToken::setString(const QString &pString)
{
    // Set the token's string

    mString = pString;
}

//==============================================================================

CompilerScanner::CompilerScanner(const QString &pInput) :
    mInput(pInput),
    mPosition(0),
    mLastPosition(pInput.length()),
    mChar(' '),   // Note: we initialise mChar with a space character, so that
                  //       we can get our first token
    mLine(1),
    mColumn(0)
{
    // Keywords for our small C mathematical grammar

    mKeywords.insert("void", CompilerScannerToken::Void);
    mKeywords.insert("double", CompilerScannerToken::Double);
}

//==============================================================================

QChar CompilerScanner::getChar()
{
    if (mPosition == mLastPosition) {
       // End of the input, so return an empty character

        mChar = QChar();
    } else {
        // Not at the end of the input, so retrieve the current character

        mChar = mInput.at(mPosition);

        // Check whether the current character is a line feed

        if (mChar == QChar(10)) {
            // The current character is a line feed, so start a new line

            ++mLine;
            mColumn = 0;
        }

        // Update the column number

        ++mColumn;

        // Get ready for the next character

        ++mPosition;
    }

    // Return the new current character

    return mChar;
}

//==============================================================================

void CompilerScanner::getWord(CompilerScannerToken &pToken)
{
    // Retrieve a word starting with either a letter or an underscore (which we
    // have already scanned) followed by zero or more letters, digits and/or
    // underscores
    // EBNF: Letter|"_" { Letter|Digit|"_" } .

    QString word = QString(mChar);

    while (getChar().isLetter() || mChar.isDigit() || (mChar == Underscore))
        // The new current character is either a letter, digit or underscore, so
        // add it to our word

        word += mChar;

    // Update the token with the word we have just scanned

    pToken.setString(word);

    // Check whether the word is a known keyword

    CompilerScannerKeywords::const_iterator keyword = mKeywords.find(word);

    if (keyword != mKeywords.end()) {
        // The word we scanned is a known keyword, so retrieve its corresponding
        // symbol

        pToken.setSymbol(keyword.value());
    } else {
        // The word we scanned is not a keyword, so it has to be an identifier,
        // unless it's only made of underscores, so remove all the underscores
        // from our word and check whether we end up with an empty string

        word.replace(Underscore, "");

        if (word.isEmpty())
            // The word we scanned only contains underscores, so we are dealing
            // with an unknown symbol

            pToken.setSymbol(CompilerScannerToken::Unknown);
        else
            // The word we scanned doesn't only contain underscores, so we are
            // dealing with an identifier

            pToken.setSymbol(CompilerScannerToken::Identifier);
    }
}

//==============================================================================

CompilerScannerToken CompilerScanner::getToken()
{
    // Skip spaces of all sorts
    // Note: we must test the current character first before getting a new
    //       one in case two tokens follow one another without any space between
    //       them...

    if (mChar.isSpace())
        while (getChar().isSpace());

    // Initialise the token

    CompilerScannerToken res = CompilerScannerToken(mLine, mColumn);

    // Check the type of the current character

    if (mChar.isLetter() || (mChar == Underscore)) {
        // The current character is a letter or an underscore, so we should try
        // to retrieve a word

        getWord(res);
    } else {
        // Not a word or a number, so it has to be a one- or two-character token

        res.setString(mChar);

        if (mChar == OpeningBracket)
            res.setSymbol(CompilerScannerToken::OpeningBracket);
        else if (mChar == ClosingBracket)
            res.setSymbol(CompilerScannerToken::ClosingBracket);
        else if (mChar == OpeningCurlyBracket)
            res.setSymbol(CompilerScannerToken::OpeningCurlyBracket);
        else if (mChar == ClosingCurlyBracket)
            res.setSymbol(CompilerScannerToken::ClosingCurlyBracket);

        // Get the next character

        getChar();
    }

    // Return the token

    return res;
}

//==============================================================================

}   // namespace Compiler
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Minor fix to our scanner.<commit_after>//==============================================================================
// Compiler scanner class
//==============================================================================

#include "compilerscanner.h"

//==============================================================================

namespace OpenCOR {
namespace Compiler {

//==============================================================================

static const QChar Underscore          = QChar('_');
static const QChar OpeningBracket      = QChar('(');
static const QChar ClosingBracket      = QChar(')');
static const QChar OpeningCurlyBracket = QChar('{');
static const QChar ClosingCurlyBracket = QChar('}');

//==============================================================================

CompilerScannerToken::CompilerScannerToken(const int pLine, const int pColumn) :
    mLine(pLine),
    mColumn(pColumn),
    mSymbol(Eof),
    mString(QString())
{
}

//==============================================================================

int CompilerScannerToken::line() const
{
    // Return the token's line

    return mLine;
}

//==============================================================================

int CompilerScannerToken::column() const
{
    // Return the token's column

    return mColumn;
}

//==============================================================================

CompilerScannerToken::Symbol CompilerScannerToken::symbol() const
{
    // Return the token's symbol

    return mSymbol;
}

//==============================================================================

QString CompilerScannerToken::symbolAsString() const
{
    // Return the token's symbol as a string

    switch (mSymbol) {
    case Void:
        return "Void";
    case Double:
        return "Double";
    case OpeningBracket:
        return "OpeningBracket";
    case ClosingBracket:
        return "ClosingBracket";
    case OpeningCurlyBracket:
        return "OpeningCurlyBracket";
    case ClosingCurlyBracket:
        return "ClosingCurlyBracket";
    case Unknown:
        return "Unknown";
    case Identifier:
        return "Identifier";
    case Eof:
        return "Eof";
    default:
        return "???";
    }
}

//==============================================================================

void CompilerScannerToken::setSymbol(const Symbol &pSymbol)
{
    // Set the token's symbol

    mSymbol = pSymbol;
}

//==============================================================================

QString CompilerScannerToken::string() const
{
    // Return the token's string

    return mString;
}

//==============================================================================

void CompilerScannerToken::setString(const QString &pString)
{
    // Set the token's string

    mString = pString;
}

//==============================================================================

CompilerScanner::CompilerScanner(const QString &pInput) :
    mInput(pInput),
    mPosition(0),
    mLastPosition(pInput.length()),
    mChar(' '),   // Note: we initialise mChar with a space character, so that
                  //       we can get our first token
    mLine(1),
    mColumn(0)
{
    // Keywords for our small C mathematical grammar

    mKeywords.insert("void", CompilerScannerToken::Void);
    mKeywords.insert("double", CompilerScannerToken::Double);
}

//==============================================================================

QChar CompilerScanner::getChar()
{
    if (mPosition == mLastPosition) {
       // End of the input, so return an empty character

        mChar = QChar();

        // Update the column number

        ++mColumn;
    } else {
        // Not at the end of the input, so retrieve the current character

        mChar = mInput.at(mPosition);

        // Check whether the current character is a line feed

        if (mChar == QChar(10)) {
            // The current character is a line feed, so start a new line

            ++mLine;
            mColumn = 0;
        }

        // Update the column number

        ++mColumn;

        // Get ready for the next character

        ++mPosition;
    }

    // Return the new current character

    return mChar;
}

//==============================================================================

void CompilerScanner::getWord(CompilerScannerToken &pToken)
{
    // Retrieve a word starting with either a letter or an underscore (which we
    // have already scanned) followed by zero or more letters, digits and/or
    // underscores
    // EBNF: Letter|"_" { Letter|Digit|"_" } .

    QString word = QString(mChar);

    while (getChar().isLetter() || mChar.isDigit() || (mChar == Underscore))
        // The new current character is either a letter, digit or underscore, so
        // add it to our word

        word += mChar;

    // Update the token with the word we have just scanned

    pToken.setString(word);

    // Check whether the word is a known keyword

    CompilerScannerKeywords::const_iterator keyword = mKeywords.find(word);

    if (keyword != mKeywords.end()) {
        // The word we scanned is a known keyword, so retrieve its corresponding
        // symbol

        pToken.setSymbol(keyword.value());
    } else {
        // The word we scanned is not a keyword, so it has to be an identifier,
        // unless it's only made of underscores, so remove all the underscores
        // from our word and check whether we end up with an empty string

        word.replace(Underscore, "");

        if (word.isEmpty())
            // The word we scanned only contains underscores, so we are dealing
            // with an unknown symbol

            pToken.setSymbol(CompilerScannerToken::Unknown);
        else
            // The word we scanned doesn't only contain underscores, so we are
            // dealing with an identifier

            pToken.setSymbol(CompilerScannerToken::Identifier);
    }
}

//==============================================================================

CompilerScannerToken CompilerScanner::getToken()
{
    // Skip spaces of all sorts
    // Note: we must test the current character first before getting a new
    //       one in case two tokens follow one another without any space between
    //       them...

    if (mChar.isSpace())
        while (getChar().isSpace());

    // Initialise the token

    CompilerScannerToken res = CompilerScannerToken(mLine, mColumn);

    // Check the type of the current character

    if (mChar.isLetter() || (mChar == Underscore)) {
        // The current character is a letter or an underscore, so we should try
        // to retrieve a word

        getWord(res);
    } else {
        // Not a word or a number, so it has to be a one- or two-character token

        res.setString(mChar);

        if (mChar == OpeningBracket)
            res.setSymbol(CompilerScannerToken::OpeningBracket);
        else if (mChar == ClosingBracket)
            res.setSymbol(CompilerScannerToken::ClosingBracket);
        else if (mChar == OpeningCurlyBracket)
            res.setSymbol(CompilerScannerToken::OpeningCurlyBracket);
        else if (mChar == ClosingCurlyBracket)
            res.setSymbol(CompilerScannerToken::ClosingCurlyBracket);

        // Get the next character

        getChar();
    }

    // Return the token

    return res;
}

//==============================================================================

}   // namespace Compiler
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>