<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/thread_management.h>
#include <deal.II/base/subscriptor.h>
#include <deal.II/base/logstream.h>

#include <typeinfo>
#include <string>
#include <iostream>

DEAL_II_NAMESPACE_OPEN


#ifdef DEBUG
namespace
{
// create a lock that might be used to control subscription to and
// unsubscription from objects, as that might happen in parallel.
// since it should happen rather seldom that several threads try to
// operate on different objects at the same time (the usual case is
// that they subscribe to the same object right after thread
// creation), a global lock should be sufficient, rather than one that
// operates on a per-object base (in which case we would have to
// include the huge <thread_management.h> file into the
// <subscriptor.h> file).
  Threads::Mutex subscription_lock;
}
#endif


static const char *unknown_subscriber = "unknown subscriber";


Subscriptor::Subscriptor ()
  :
  counter (0),
  object_info (0)
{
  // this has to go somewhere to avoid an extra warning.
  (void)unknown_subscriber;
}



Subscriptor::Subscriptor (const Subscriptor &)
  :
  counter (0),
  object_info (0)
{}



#ifdef DEAL_II_WITH_CXX11
Subscriptor::Subscriptor (Subscriptor &&subscriptor)
  :
  counter(0),
  object_info (subscriptor.object_info)
{
  subscriptor.check_no_subscribers();
  subscriptor.counter = 0;
  subscriptor.counter_map.clear();
}
#endif



Subscriptor::~Subscriptor ()
{
  check_no_subscribers();
  counter = 0;
  counter_map.clear();

#ifdef DEAL_II_WITH_CXX11
  object_info = nullptr;
#else
  object_info = 0;
#endif
}


void Subscriptor::check_no_subscribers () const
{
  // Check whether there are still subscriptions to this object. If so, output
  // the actual name of the class to which this object belongs, i.e. the most
  // derived class. Note that the name may be mangled, so it need not be the
  // clear-text class name. However, you can obtain the latter by running the
  // c++filt program over the output.
#ifdef DEBUG

  // If there are still active pointers, show a message and kill the program.
  // However, under some circumstances, this is not so desirable. For example,
  // in code like this:
  //
  //     Triangulation tria;
  //     DoFHandler *dh = new DoFHandler(tria);
  //     ...some function that throws an exception
  //
  // the exception will lead to the destruction of the triangulation, but since
  // the dof_handler is on the heap it will not be destroyed. This will trigger
  // an assertion in the triangulation. If we kill the program at this point, we
  // will never be able to learn what caused the problem. In this situation,
  // just display a message and continue the program.
  if (counter != 0)
    {
      if (std::uncaught_exception() == false)
        {
          std::string infostring;
          for (map_iterator it = counter_map.begin(); it != counter_map.end(); ++it)
            {
              if (it->second > 0)
                infostring += std::string("\n  from Subscriber ")
                              + std::string(it->first);
            }

          if (infostring == "")
            infostring = "<none>";

          AssertNothrow (counter == 0,
                         ExcInUse (counter, object_info->name(), infostring));
        }
      else
        {
          std::cerr << "---------------------------------------------------------"
                    << std::endl
                    << "An object pointed to by a SmartPointer is being destroyed."
                    << std::endl
                    << "Under normal circumstances, this would abort the program."
                    << std::endl
                    << "However, another exception is being processed at the"
                    << std::endl
                    << "moment, so the program will continue to run to allow"
                    << std::endl
                    << "this exception to be processed."
                    << std::endl
                    << "---------------------------------------------------------"
                    << std::endl;
        }
    }

#endif
}



Subscriptor &Subscriptor::operator = (const Subscriptor &s)
{
  object_info = s.object_info;
  return *this;
}



void
Subscriptor::subscribe(const char *id) const
{
#ifdef DEBUG
  if (object_info == 0)
    object_info = &typeid(*this);
  Threads::Mutex::ScopedLock lock (subscription_lock);
  ++counter;

#  ifndef DEAL_II_WITH_THREADS
  const char *const name = (id != 0) ? id : unknown_subscriber;

  map_iterator it = counter_map.find(name);
  if (it == counter_map.end())
    counter_map.insert(map_value_type(name, 1U));

  else
    it->second++;
#  else
  (void)id;
#  endif
#else
  (void)id;
#endif
}


void
Subscriptor::unsubscribe(const char *id) const
{
#ifdef DEBUG
  const char *name = (id != 0) ? id : unknown_subscriber;
  AssertNothrow (counter>0, ExcNoSubscriber(object_info->name(), name));
  // This is for the case that we do
  // not abort after the exception
  if (counter == 0)
    return;

  Threads::Mutex::ScopedLock lock (subscription_lock);
  --counter;

#  ifndef DEAL_II_WITH_THREADS
  map_iterator it = counter_map.find(name);
  AssertNothrow (it != counter_map.end(), ExcNoSubscriber(object_info->name(), name));
  AssertNothrow (it->second > 0, ExcNoSubscriber(object_info->name(), name));

  it->second--;
#  endif
#else
  (void)id;
#endif
}



unsigned int Subscriptor::n_subscriptions () const
{
  return counter;
}



void Subscriptor::list_subscribers () const
{
#ifndef DEAL_II_WITH_THREADS
  for (map_iterator it = counter_map.begin();
       it != counter_map.end(); ++it)
    deallog << it->second << '/'
            << counter << " subscriptions from \""
            << it->first << '\"' << std::endl;
#else
  deallog << "No subscriber listing with multithreading" << std::endl;
#endif
}

DEAL_II_NAMESPACE_CLOSE
<commit_msg>Removed unnecessary cleanup in subscriptor dtor/move ctor<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/thread_management.h>
#include <deal.II/base/subscriptor.h>
#include <deal.II/base/logstream.h>

#include <typeinfo>
#include <string>
#include <iostream>

DEAL_II_NAMESPACE_OPEN


#ifdef DEBUG
namespace
{
// create a lock that might be used to control subscription to and
// unsubscription from objects, as that might happen in parallel.
// since it should happen rather seldom that several threads try to
// operate on different objects at the same time (the usual case is
// that they subscribe to the same object right after thread
// creation), a global lock should be sufficient, rather than one that
// operates on a per-object base (in which case we would have to
// include the huge <thread_management.h> file into the
// <subscriptor.h> file).
  Threads::Mutex subscription_lock;
}
#endif


static const char *unknown_subscriber = "unknown subscriber";


Subscriptor::Subscriptor ()
  :
  counter (0),
  object_info (0)
{
  // this has to go somewhere to avoid an extra warning.
  (void)unknown_subscriber;
}



Subscriptor::Subscriptor (const Subscriptor &)
  :
  counter (0),
  object_info (0)
{}



#ifdef DEAL_II_WITH_CXX11
Subscriptor::Subscriptor (Subscriptor &&subscriptor)
  :
  counter(0),
  object_info (subscriptor.object_info)
{
  subscriptor.check_no_subscribers();
}
#endif



Subscriptor::~Subscriptor ()
{
  check_no_subscribers();

#ifdef DEAL_II_WITH_CXX11
  object_info = nullptr;
#else
  object_info = 0;
#endif
}


void Subscriptor::check_no_subscribers () const
{
  // Check whether there are still subscriptions to this object. If so, output
  // the actual name of the class to which this object belongs, i.e. the most
  // derived class. Note that the name may be mangled, so it need not be the
  // clear-text class name. However, you can obtain the latter by running the
  // c++filt program over the output.
#ifdef DEBUG

  // If there are still active pointers, show a message and kill the program.
  // However, under some circumstances, this is not so desirable. For example,
  // in code like this:
  //
  //     Triangulation tria;
  //     DoFHandler *dh = new DoFHandler(tria);
  //     ...some function that throws an exception
  //
  // the exception will lead to the destruction of the triangulation, but since
  // the dof_handler is on the heap it will not be destroyed. This will trigger
  // an assertion in the triangulation. If we kill the program at this point, we
  // will never be able to learn what caused the problem. In this situation,
  // just display a message and continue the program.
  if (counter != 0)
    {
      if (std::uncaught_exception() == false)
        {
          std::string infostring;
          for (map_iterator it = counter_map.begin(); it != counter_map.end(); ++it)
            {
              if (it->second > 0)
                infostring += std::string("\n  from Subscriber ")
                              + std::string(it->first);
            }

          if (infostring == "")
            infostring = "<none>";

          AssertNothrow (counter == 0,
                         ExcInUse (counter, object_info->name(), infostring));
        }
      else
        {
          std::cerr << "---------------------------------------------------------"
                    << std::endl
                    << "An object pointed to by a SmartPointer is being destroyed."
                    << std::endl
                    << "Under normal circumstances, this would abort the program."
                    << std::endl
                    << "However, another exception is being processed at the"
                    << std::endl
                    << "moment, so the program will continue to run to allow"
                    << std::endl
                    << "this exception to be processed."
                    << std::endl
                    << "---------------------------------------------------------"
                    << std::endl;
        }
    }

#endif
}



Subscriptor &Subscriptor::operator = (const Subscriptor &s)
{
  object_info = s.object_info;
  return *this;
}



void
Subscriptor::subscribe(const char *id) const
{
#ifdef DEBUG
  if (object_info == 0)
    object_info = &typeid(*this);
  Threads::Mutex::ScopedLock lock (subscription_lock);
  ++counter;

#  ifndef DEAL_II_WITH_THREADS
  const char *const name = (id != 0) ? id : unknown_subscriber;

  map_iterator it = counter_map.find(name);
  if (it == counter_map.end())
    counter_map.insert(map_value_type(name, 1U));

  else
    it->second++;
#  else
  (void)id;
#  endif
#else
  (void)id;
#endif
}


void
Subscriptor::unsubscribe(const char *id) const
{
#ifdef DEBUG
  const char *name = (id != 0) ? id : unknown_subscriber;
  AssertNothrow (counter>0, ExcNoSubscriber(object_info->name(), name));
  // This is for the case that we do
  // not abort after the exception
  if (counter == 0)
    return;

  Threads::Mutex::ScopedLock lock (subscription_lock);
  --counter;

#  ifndef DEAL_II_WITH_THREADS
  map_iterator it = counter_map.find(name);
  AssertNothrow (it != counter_map.end(), ExcNoSubscriber(object_info->name(), name));
  AssertNothrow (it->second > 0, ExcNoSubscriber(object_info->name(), name));

  it->second--;
#  endif
#else
  (void)id;
#endif
}



unsigned int Subscriptor::n_subscriptions () const
{
  return counter;
}



void Subscriptor::list_subscribers () const
{
#ifndef DEAL_II_WITH_THREADS
  for (map_iterator it = counter_map.begin();
       it != counter_map.end(); ++it)
    deallog << it->second << '/'
            << counter << " subscriptions from \""
            << it->first << '\"' << std::endl;
#else
  deallog << "No subscriber listing with multithreading" << std::endl;
#endif
}

DEAL_II_NAMESPACE_CLOSE

{'fraction_non_alphanumeric': 0.14471858134155743, 'fraction_numerical': 0.004780262143407864, 'mean_word_length': 2.348218895198761, 'pattern_counts': {'":': 0, '<': 113, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7430525', 'n_tokens_mistral': 3854, 'n_tokens_neox': 3697, 'n_words': 1274}