<commit_before>// Copyright (c) 2009 OpenDNS, LLC. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "stdafx.h"

#include "StrUtil.h"

// single-linked list of string/time values
typedef struct StringTimeNode {
	struct StringTimeNode *next;
	char *s;
	time_t t;
} StringTimeNode;

StringTimeNode *AllocStringTimeNode(char *s)
{
	StringTimeNode *node = (StringTimeNode*)calloc(1, sizeof(StringTimeNode));
	if (!node)
		return NULL;
	node->s = strdup(s);
	if (!node->s) {
		free(node);
		return NULL;
	}
	time(&node->t);
	return node;
}

void InsertStringTimeNode(StringTimeNode **head, StringTimeNode *node)
{
	if (!node)
		return;
	if (!*head) {
		*head = node;
	} else {
		node->next = *head;
		*head = node;
	}
}

void AddToListIfServer(StringTimeNode **head, NETRESOURCE *nr)
{
	if (RESOURCEDISPLAYTYPE_SERVER != nr->dwDisplayType)
		return;

	LPTSTR name = nr->lpRemoteName;
	// netbios names must start with "\\"
	if (*name++ != '\\')
		return;
	if (*name++ != '\\')
		return;

	char *name2 = TStrToStr(name);
	if (!name2)
		return;
	StringTimeNode *node = AllocStringTimeNode(name2);
	InsertStringTimeNode(head, node);
	free(name2);
}

BOOL GetNetworkServersEnum(StringTimeNode** head, NETRESOURCE *nr)
{
	HANDLE hEnum;
	DWORD cbBuffer = 16384;
	NETRESOURCE *nrLocal;
	DWORD dwResultEnum;
	DWORD cEntries = 0;
	DWORD i;

	DWORD dwResult = WNetOpenEnum(RESOURCE_GLOBALNET,
									RESOURCETYPE_ANY,
									RESOURCEUSAGE_CONTAINER,
									nr,
									&hEnum);

	if (dwResult != NO_ERROR)
		return FALSE;

	nrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
	if (!nrLocal)
		return FALSE;

	for(;;) {
		ZeroMemory(nrLocal, cbBuffer);
		dwResultEnum = WNetEnumResource(hEnum, &cEntries, nrLocal, &cbBuffer);
		if (dwResultEnum != NO_ERROR)
			break;

		for (i = 0; i < cEntries; i++) {
			AddToListIfServer(head, &nrLocal[i]);
			if (RESOURCEUSAGE_CONTAINER == (nrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)) {
				GetNetworkServersEnum(head, &nrLocal[i]);
			}
		}
	}

	GlobalFree((HGLOBAL) nrLocal);
	dwResult = WNetCloseEnum(hEnum);

	if (dwResult != NO_ERROR)
		return FALSE;

	return TRUE;
}

void FreeStringTimeList(StringTimeNode *head)
{
	StringTimeNode *next;
	StringTimeNode *curr = head;
	while (curr) {
		next = curr->next;
		free(curr->s);
		free(curr);
		curr = next;
	}
}

StringTimeNode* GetNetworkServers()
{
	StringTimeNode *head = NULL;
	NETRESOURCE* nr = NULL;
	GetNetworkServersEnum(&head, nr);
	return head;
}

static void *HEAP_ALLOC(SIZE_T x) {
	return HeapAlloc(GetProcessHeap(), 0, x);
}

static void HEAP_FREE(void *x) {
	HeapFree(GetProcessHeap(), 0, x);
}

void GetDNSPrefixes(StringTimeNode **head)
{
	DWORD dwRetVal = 0;

	ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
	ULONG family = AF_UNSPEC;

	PIP_ADAPTER_ADDRESSES pAddresses = NULL;
	ULONG outBufLen = 0;

	PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;

	outBufLen = sizeof(IP_ADAPTER_ADDRESSES);
	pAddresses = (IP_ADAPTER_ADDRESSES *)HEAP_ALLOC(outBufLen);
	if (pAddresses == NULL)
		return;

	// Make an initial call to GetAdaptersAddresses to get the
	// size needed into the outBufLen variable
	ULONG ret = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
	if (ERROR_BUFFER_OVERFLOW == ret) {
		HEAP_FREE(pAddresses);
		pAddresses = (IP_ADAPTER_ADDRESSES *) HEAP_ALLOC(outBufLen);
	}

	if (pAddresses == NULL)
		return;

	dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);

	if (dwRetVal == NO_ERROR) {
		pCurrAddresses = pAddresses;
		while (pCurrAddresses) {
			WCHAR *dnsSuffix = pCurrAddresses->DnsSuffix;
			if (dnsSuffix && *dnsSuffix) {
				char *dnsSuffix2 = WstrToUtf8(dnsSuffix);
				if (dnsSuffix2) {
					StringTimeNode *node = AllocStringTimeNode(dnsSuffix2);
					InsertStringTimeNode(head, node);
				}
				free(dnsSuffix2);
			}
			pCurrAddresses = pCurrAddresses->Next;
		}
	}
	HEAP_FREE(pAddresses);
	return;
}

void ListServersAndDnsSuffixes()
{
	NETRESOURCE* nr = NULL;
	StringTimeNode *list = NULL;
	GetDNSPrefixes(&list);
	GetNetworkServersEnum(&list, nr);
	FreeStringTimeList(list);
}

<commit_msg>tighten the code a bit<commit_after>// Copyright (c) 2009 OpenDNS, LLC. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "stdafx.h"

#include "StrUtil.h"

// single-linked list of string/time values
typedef struct StringTimeNode {
	struct StringTimeNode *next;
	char *s;
	time_t t;
} StringTimeNode;

StringTimeNode *AllocStringTimeNode(char *s)
{
	if (!s)
		return NULL;
	StringTimeNode *node = (StringTimeNode*)calloc(1, sizeof(StringTimeNode));
	if (!node)
		return NULL;
	node->s = strdup(s);
	if (!node->s) {
		free(node);
		return NULL;
	}
	time(&node->t);
	return node;
}

static void InsertStringTimeNode(StringTimeNode **head, StringTimeNode *node)
{
	if (!node)
		return;
	if (!*head) {
		*head = node;
	} else {
		node->next = *head;
		*head = node;
	}
}

static void AllocAndInsertStringTimeNode(StringTimeNode **head, char *s)
{
	StringTimeNode *node = AllocStringTimeNode(s);
	InsertStringTimeNode(head, node);
	free(s);
}

static void AddToListIfServer(StringTimeNode **head, NETRESOURCE *nr)
{
	if (RESOURCEDISPLAYTYPE_SERVER != nr->dwDisplayType)
		return;

	LPTSTR name = nr->lpRemoteName;
	// netbios names must start with "\\"
	if (*name++ != '\\')
		return;
	if (*name++ != '\\')
		return;

	char *name2 = TStrToStr(name);
	AllocAndInsertStringTimeNode(head, name2); // name2 freed inside
}

static BOOL GetNetworkServersEnum(StringTimeNode** head, NETRESOURCE *nr)
{
	HANDLE hEnum;
	DWORD cbBuffer = 16384;
	NETRESOURCE *nrLocal;
	DWORD dwResultEnum;
	DWORD cEntries = 0;
	DWORD i;

	DWORD dwResult = WNetOpenEnum(RESOURCE_GLOBALNET,
									RESOURCETYPE_ANY,
									RESOURCEUSAGE_CONTAINER,
									nr,
									&hEnum);

	if (dwResult != NO_ERROR)
		return FALSE;

	nrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
	if (!nrLocal)
		return FALSE;

	for(;;) {
		ZeroMemory(nrLocal, cbBuffer);
		dwResultEnum = WNetEnumResource(hEnum, &cEntries, nrLocal, &cbBuffer);
		if (dwResultEnum != NO_ERROR)
			break;

		for (i = 0; i < cEntries; i++) {
			AddToListIfServer(head, &nrLocal[i]);
			if (RESOURCEUSAGE_CONTAINER == (nrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)) {
				GetNetworkServersEnum(head, &nrLocal[i]);
			}
		}
	}

	GlobalFree((HGLOBAL) nrLocal);
	dwResult = WNetCloseEnum(hEnum);

	if (dwResult != NO_ERROR)
		return FALSE;

	return TRUE;
}

void FreeStringTimeList(StringTimeNode *head)
{
	StringTimeNode *next;
	StringTimeNode *curr = head;
	while (curr) {
		next = curr->next;
		free(curr->s);
		free(curr);
		curr = next;
	}
}

StringTimeNode* GetNetworkServers()
{
	StringTimeNode *head = NULL;
	NETRESOURCE* nr = NULL;
	GetNetworkServersEnum(&head, nr);
	return head;
}

static void *HEAP_ALLOC(SIZE_T x) {
	return HeapAlloc(GetProcessHeap(), 0, x);
}

static void HEAP_FREE(void *x) {
	HeapFree(GetProcessHeap(), 0, x);
}

void GetDNSPrefixes(StringTimeNode **head)
{
	DWORD dwRetVal = 0;

	ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
	ULONG family = AF_UNSPEC;

	PIP_ADAPTER_ADDRESSES pAddresses = NULL;
	ULONG outBufLen = 0;

	PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;

	outBufLen = sizeof(IP_ADAPTER_ADDRESSES);
	pAddresses = (IP_ADAPTER_ADDRESSES *)HEAP_ALLOC(outBufLen);
	if (pAddresses == NULL)
		return;

	// Make an initial call to GetAdaptersAddresses to get the
	// size needed into the outBufLen variable
	ULONG ret = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
	if (ERROR_BUFFER_OVERFLOW == ret) {
		HEAP_FREE(pAddresses);
		pAddresses = (IP_ADAPTER_ADDRESSES *) HEAP_ALLOC(outBufLen);
	}

	if (pAddresses == NULL)
		return;

	dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);

	if (dwRetVal == NO_ERROR) {
		pCurrAddresses = pAddresses;
		while (pCurrAddresses) {
			WCHAR *dnsSuffix = pCurrAddresses->DnsSuffix;
			if (dnsSuffix && *dnsSuffix) {
				char *dnsSuffix2 = WstrToUtf8(dnsSuffix);
				AllocAndInsertStringTimeNode(head, dnsSuffix2); // dnsSuffix2 freed inside
			}
			pCurrAddresses = pCurrAddresses->Next;
		}
	}
	HEAP_FREE(pAddresses);
	return;
}

// result must be freed by FreeStringTimeList()
StringTimeNode* GetTypoExceptions()
{
	StringTimeNode *list = NULL;
	GetDNSPrefixes(&list);
	GetNetworkServersEnum(&list, NULL);
	return list;
}

<|endoftext|>


<commit_before><commit_msg>Fix some stuff with UIDPointer<commit_after><|endoftext|>


<commit_before><commit_msg>mapi: serum circles<commit_after><|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/qtree/UnionNode.h>

using namespace stx;

namespace csql {

UnionNode::UnionNode(const UnionNode& other) {
  for (const auto& tbl : other.tables_) {
    tables_.emplace_back(tbl->deepCopy());
  }

  for (auto& table : tables_) {
    addChild(&table);
  }
}

UnionNode::UnionNode(
    Vector<RefPtr<QueryTreeNode>> tables) :
    tables_(tables) {
  for (auto& table : tables_) {
    addChild(&table);
  }
}

Vector<RefPtr<QueryTreeNode>> UnionNode::inputTables() const {
  return tables_;
}

RefPtr<QueryTreeNode> UnionNode::deepCopy() const {
  return new UnionNode(*this);
}

} // namespace csql
<commit_msg>UnionNode::toString<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/qtree/UnionNode.h>

using namespace stx;

namespace csql {

UnionNode::UnionNode(const UnionNode& other) {
  for (const auto& tbl : other.tables_) {
    tables_.emplace_back(tbl->deepCopy());
  }

  for (auto& table : tables_) {
    addChild(&table);
  }
}

UnionNode::UnionNode(
    Vector<RefPtr<QueryTreeNode>> tables) :
    tables_(tables) {
  for (auto& table : tables_) {
    addChild(&table);
  }
}

Vector<RefPtr<QueryTreeNode>> UnionNode::inputTables() const {
  return tables_;
}

RefPtr<QueryTreeNode> UnionNode::deepCopy() const {
  return new UnionNode(*this);
}

String UnionNode::toString() const {
  String str = "(union";

  for (const auto& tbl : tables_) {
    str += " (subexpr " + tbl->toString() + ")";
  }

  str += ")";
  return str;
}

} // namespace csql
<|endoftext|>


<commit_before>/*
 * SphInterface.cpp
 *
 *  Created on: Mar 2, 2015
 *      Author: arman
 */

#include "SphInterface.h"

//------------------------------------------------------------------------------------
void AddSphDataToChSystem(chrono::ChSystemParallelDVI& mphysicalSystem,
                          int& startIndexSph,
                          const thrust::host_vector<Real3>& posRadH,
                          const thrust::host_vector<Real4>& velMasH,
                          const SimParams& paramsH,
                          const NumberOfObjects& numObjects,
                          int collisionFamilly) {
  Real rad = 0.5 * paramsH.MULT_INITSPACE * paramsH.HSML;
  // NOTE: mass properties and shapes are all for sphere
  double volume = chrono::utils::CalcSphereVolume(rad);
  chrono::ChVector<> gyration = chrono::utils::CalcSphereGyration(rad).Get_Diag();
  double density = paramsH.rho0;
  double mass = density * volume;
  double muFriction = 0;

  // int fId = 0; //fluid id

  // Create a common material
  chrono::ChSharedPtr<chrono::ChMaterialSurface> mat_g(new chrono::ChMaterialSurface);
  mat_g->SetFriction(muFriction);
  mat_g->SetCohesion(0);
  mat_g->SetCompliance(0.0);
  mat_g->SetComplianceT(0.0);
  mat_g->SetDampingF(0.2);

  const chrono::ChQuaternion<> rot = chrono::ChQuaternion<>(1, 0, 0, 0);

  startIndexSph = mphysicalSystem.Get_bodylist()->size();
  // openmp does not work here
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    Real3 p3 = posRadH[i];
    Real4 vM4 = velMasH[i];
    chrono::ChVector<> pos = chrono::ChVector<>(p3.x, p3.y, p3.z);
    chrono::ChVector<> vel = chrono::ChVector<>(vM4.x, vM4.y, vM4.z);
    chrono::ChSharedBodyPtr body;
    body = chrono::ChSharedBodyPtr(new chrono::ChBody(new chrono::collision::ChCollisionModelParallel));
    body->SetMaterialSurface(mat_g);
    // body->SetIdentifier(fId);
    body->SetPos(pos);
    body->SetRot(rot);
    body->SetCollide(true);
    body->SetBodyFixed(false);
    body->SetMass(mass);
    body->SetInertiaXX(mass * gyration);

    body->GetCollisionModel()->ClearModel();

    // add collision geometry
    //	body->GetCollisionModel()->AddEllipsoid(size.x, size.y, size.z, pos, rot);
    //
    //	// add asset (for visualization)
    //	ChSharedPtr<ChEllipsoidShape> ellipsoid(new ChEllipsoidShape);
    //	ellipsoid->GetEllipsoidGeometry().rad = size;
    //	ellipsoid->Pos = pos;
    //	ellipsoid->Rot = rot;
    //
    //	body->GetAssets().push_back(ellipsoid);

    //	chrono::utils::AddCapsuleGeometry(body.get_ptr(), size.x, size.y);		// X
    //	chrono::utils::AddCylinderGeometry(body.get_ptr(), size.x, size.y);		// O
    //	chrono::utils::AddConeGeometry(body.get_ptr(), size.x, size.y); 		// X
    //	chrono::utils::AddBoxGeometry(body.get_ptr(), size);					// O
    chrono::utils::AddSphereGeometry(body.get_ptr(), rad);  // O
                                                    //	chrono::utils::AddEllipsoidGeometry(body.get_ptr(), size);					// X

    body->GetCollisionModel()->SetFamily(collisionFamilly);
    body->GetCollisionModel()->SetFamilyMaskNoCollisionWithFamily(collisionFamilly);

    body->GetCollisionModel()->BuildModel();
    mphysicalSystem.AddBody(body);
  }
}
//------------------------------------------------------------------------------------
void AddHydroForce(chrono::ChSystemParallelDVI& mphysicalSystem,
                          int& startIndexSph,
                          const NumberOfObjects& numObjects) {
  // openmp does not work here
	std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
	for (int i = 0; i < numObjects.numFluidMarkers; i++) {
		char forceTag[] = "hydrodynamics_force";
		chrono::ChSharedPtr<chrono::ChForce> hydroForce = (*(bodyIter + i))->SearchForce(forceTag);
		if (hydroForce.IsNull()) {
			hydroForce = chrono::ChSharedPtr<chrono::ChForce>(new chrono::ChForce);
			hydroForce->SetMode(
			  FTYPE_FORCE);  // no need for this. It is the default option.
			(*(bodyIter + i))->AddForce(hydroForce);
			// ** or: hydroForce = ChSharedPtr<ChForce>(new ChForce());
			hydroForce->SetName(forceTag);
		}
	}
}
//------------------------------------------------------------------------------------
void UpdateSphDataInChSystem(chrono::ChSystemParallelDVI& mphysicalSystem,
                             const thrust::host_vector<Real3>& posRadH,
                             const thrust::host_vector<Real4>& velMasH,
                             const NumberOfObjects& numObjects,
                             int startIndexSph) {
#pragma omp parallel for
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    Real3 p3 = posRadH[i];
    Real4 vM4 = velMasH[i];
    chrono::ChVector<> pos = chrono::ChVector<>(p3.x, p3.y, p3.z);
    chrono::ChVector<> vel = chrono::ChVector<>(vM4.x, vM4.y, vM4.z);

    int chSystemBodyId = startIndexSph + i;
    std::vector<chrono::ChBody*>::iterator ibody = mphysicalSystem.Get_bodylist()->begin() + chSystemBodyId;
    (*ibody)->SetPos(pos);
    (*ibody)->SetPos_dt(vel);
  }
}
//------------------------------------------------------------------------------------
void AddChSystemForcesToSphForces(thrust::host_vector<Real4>& derivVelRhoChronoH,
                                  const thrust::host_vector<Real4>& velMasH2,
                                  chrono::ChSystemParallelDVI& mphysicalSystem,
                                  const NumberOfObjects& numObjects,
                                  int startIndexSph,
                                  Real dT) {
  std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    chrono::ChVector<> v = ((chrono::ChBody*)(*(bodyIter + i)))->GetPos_dt();
    Real3 a3 = (mR3(v.x, v.y, v.z) - mR3(velMasH2[i])) / dT;  // f = m * a
    derivVelRhoChronoH[i] += mR4(a3, 0);                      // note, gravity force is also coming from rigid system
  }
}
//------------------------------------------------------------------------------------

void ClearArraysH(thrust::host_vector<Real3>& posRadH,  // do not set the size here since you are using push back later
                  thrust::host_vector<Real4>& velMasH,
                  thrust::host_vector<Real4>& rhoPresMuH) {
  posRadH.clear();
  velMasH.clear();
  rhoPresMuH.clear();
}
//------------------------------------------------------------------------------------

void ClearArraysH(thrust::host_vector<Real3>& posRadH,  // do not set the size here since you are using push back later
                  thrust::host_vector<Real4>& velMasH,
                  thrust::host_vector<Real4>& rhoPresMuH,
                  thrust::host_vector<uint>& bodyIndex,
                  thrust::host_vector<::int3>& referenceArray) {
  ClearArraysH(posRadH, velMasH, rhoPresMuH);
  bodyIndex.clear();
  referenceArray.clear();
}
//------------------------------------------------------------------------------------

void CopyD2H(thrust::host_vector<Real4>& derivVelRhoChronoH, const thrust::device_vector<Real4>& derivVelRhoD) {
  assert(derivVelRhoChronoH.size() == derivVelRhoD.size() && "Error! size mismatch host and device");
  thrust::copy(derivVelRhoD.begin(), derivVelRhoD.end(), derivVelRhoChronoH.begin());
}

//------------------------------------------------------------------------------------
void CountNumContactsPerSph(thrust::host_vector<short int>& numContactsOnAllSph,
                                  const chrono::ChSystemParallelDVI& mphysicalSystem,
                                  const NumberOfObjects& numObjects,
                                  int startIndexSph) {
	int numContacts = mphysicalSystem.data_manager->host_data.bids_rigid_rigid.size();
#pragma omp parallel for
	for (int i = 0; i < numContacts; i ++) {
		chrono::int2 ids = mphysicalSystem.data_manager->host_data.bids_rigid_rigid[i];
		if (ids.x > startIndexSph)
			numContactsOnAllSph[ids.x - startIndexSph] += 1;
		if (ids.y > startIndexSph)
			numContactsOnAllSph[ids.y - startIndexSph] += 1;
	}
}

//------------------------------------------------------------------------------------
void CopyForceSphToChSystem(chrono::ChSystemParallelDVI& mphysicalSystem,
		const NumberOfObjects& numObjects,
		int startIndexSph,
		const thrust::device_vector<Real4>& derivVelRhoD,
		const thrust::host_vector<short int>& numContactsOnAllSph,
		Real sphMass) {

	std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
	for (int i = 0; i < numObjects.numFluidMarkers; i++) {
		char forceTag[] = "hydrodynamics_force";
		chrono::ChSharedPtr<chrono::ChForce> hydroForce = (*(bodyIter + i))->SearchForce(forceTag);
//		if (!hydroForce.IsNull())
//			hydroForce->SetMforce(0);
//
//		if (numContactsOnAllSph[i] == 0) continue;
		assert(!hydroForce.IsNull() && "Error! sph marker does not have hyroforce tag in ChSystem");

		Real4 mDerivVelRho= derivVelRhoD[i];
		Real3 forceSphMarker = mR3(mDerivVelRho) * sphMass;
		chrono::ChVector<> f3 = chrono::ChVector<>(forceSphMarker.x, forceSphMarker.y, forceSphMarker.z);
		hydroForce->SetMforce(f3.Length());
		f3.Normalize();
		hydroForce->SetDir(f3);
	}
}

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

void CopyCustomChSystemPosVel2HostThrust(
        thrust::host_vector<Real3>& posRadH,
        thrust::host_vector<Real4>& velMasH,
		chrono::ChSystemParallelDVI& mphysicalSystem,
		const NumberOfObjects& numObjects,
		int startIndexSph,
		const thrust::host_vector<short int>& numContactsOnAllSph) {

	std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
	for (int i = 0; i < numObjects.numFluidMarkers; i++) {
		if (numContactsOnAllSph[i] == 0) continue;
		chrono::ChVector<> pos = (*(bodyIter + i))->GetPos();
		posRadH[i] = mR3(pos.x, pos.y, pos.z);
		chrono::ChVector<> vel = (*(bodyIter + i))->GetPos_dt();
		Real mass = velMasH[i].w;
		velMasH[i] = mR4(vel.x, vel.y, vel.z, mass);
	}
}
//------------------------------------------------------------------------------------

void CopyH2DPosVel(
		thrust::device_vector<Real3>& posRadD,
		thrust::device_vector<Real4>& velMasD,
		const thrust::host_vector<Real3>& posRadH,
		const thrust::host_vector<Real4>& velMasH) {
  assert(posRadH.size() == posRadD.size() && "Error! size mismatch host and device");
  thrust::copy(posRadH.begin(), posRadH.end(), posRadD.begin());
  thrust::copy(velMasH.begin(), velMasH.end(), velMasD.begin());
}

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

void CopyD2HPosVel(
		thrust::host_vector<Real3>& posRadH,
		thrust::host_vector<Real4>& velMasH,
		const thrust::host_vector<Real3>& posRadD,
		const thrust::host_vector<Real4>& velMasD) {
  assert(posRadH.size() == posRadD.size() && "Error! size mismatch host and device");
  thrust::copy(posRadD.begin(), posRadD.end(), posRadH.begin());
  thrust::copy(velMasD.begin(), velMasD.end(), velMasH.begin());
}

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

void CopyH2D(thrust::device_vector<Real4>& derivVelRhoD, const thrust::host_vector<Real4>& derivVelRhoChronoH) {
  assert(derivVelRhoChronoH.size() == derivVelRhoD.size() && "Error! size mismatch host and device");
  thrust::copy(derivVelRhoChronoH.begin(), derivVelRhoChronoH.end(), derivVelRhoD.begin());
}
//------------------------------------------------------------------------------------

void CopySys2D(thrust::device_vector<Real3>& posRadD,
               chrono::ChSystemParallelDVI& mphysicalSystem,
               const NumberOfObjects& numObjects,
               int startIndexSph) {
  thrust::host_vector<Real3> posRadH(numObjects.numFluidMarkers);
  std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    chrono::ChVector<> p = ((chrono::ChBody*)(*(bodyIter + i)))->GetPos();
    posRadH[i] += mR3(p.x, p.y, p.z);
  }
  thrust::copy(posRadH.begin(), posRadH.end(), posRadD.begin());
}
//------------------------------------------------------------------------------------

void CopyD2H(thrust::host_vector<Real3>& posRadH,  // do not set the size here since you are using push back later
             thrust::host_vector<Real4>& velMasH,
             thrust::host_vector<Real4>& rhoPresMuH,
             const thrust::device_vector<Real3>& posRadD,
             const thrust::device_vector<Real4>& velMasD,
             const thrust::device_vector<Real4>& rhoPresMuD) {
  assert(posRadH.size() == posRadD.size() && "Error! size mismatch host and device");
  thrust::copy(posRadD.begin(), posRadD.end(), posRadH.begin());
  thrust::copy(velMasD.begin(), velMasD.end(), velMasH.begin());
  thrust::copy(rhoPresMuD.begin(), rhoPresMuD.end(), rhoPresMuH.begin());
}
<commit_msg>one more omp parallel loop  added<commit_after>/*
 * SphInterface.cpp
 *
 *  Created on: Mar 2, 2015
 *      Author: arman
 */

#include "SphInterface.h"

//------------------------------------------------------------------------------------
void AddSphDataToChSystem(chrono::ChSystemParallelDVI& mphysicalSystem,
                          int& startIndexSph,
                          const thrust::host_vector<Real3>& posRadH,
                          const thrust::host_vector<Real4>& velMasH,
                          const SimParams& paramsH,
                          const NumberOfObjects& numObjects,
                          int collisionFamilly) {
  Real rad = 0.5 * paramsH.MULT_INITSPACE * paramsH.HSML;
  // NOTE: mass properties and shapes are all for sphere
  double volume = chrono::utils::CalcSphereVolume(rad);
  chrono::ChVector<> gyration = chrono::utils::CalcSphereGyration(rad).Get_Diag();
  double density = paramsH.rho0;
  double mass = density * volume;
  double muFriction = 0;

  // int fId = 0; //fluid id

  // Create a common material
  chrono::ChSharedPtr<chrono::ChMaterialSurface> mat_g(new chrono::ChMaterialSurface);
  mat_g->SetFriction(muFriction);
  mat_g->SetCohesion(0);
  mat_g->SetCompliance(0.0);
  mat_g->SetComplianceT(0.0);
  mat_g->SetDampingF(0.2);

  const chrono::ChQuaternion<> rot = chrono::ChQuaternion<>(1, 0, 0, 0);

  startIndexSph = mphysicalSystem.Get_bodylist()->size();
  // openmp does not work here
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    Real3 p3 = posRadH[i];
    Real4 vM4 = velMasH[i];
    chrono::ChVector<> pos = chrono::ChVector<>(p3.x, p3.y, p3.z);
    chrono::ChVector<> vel = chrono::ChVector<>(vM4.x, vM4.y, vM4.z);
    chrono::ChSharedBodyPtr body;
    body = chrono::ChSharedBodyPtr(new chrono::ChBody(new chrono::collision::ChCollisionModelParallel));
    body->SetMaterialSurface(mat_g);
    // body->SetIdentifier(fId);
    body->SetPos(pos);
    body->SetRot(rot);
    body->SetCollide(true);
    body->SetBodyFixed(false);
    body->SetMass(mass);
    body->SetInertiaXX(mass * gyration);

    body->GetCollisionModel()->ClearModel();

    // add collision geometry
    //	body->GetCollisionModel()->AddEllipsoid(size.x, size.y, size.z, pos, rot);
    //
    //	// add asset (for visualization)
    //	ChSharedPtr<ChEllipsoidShape> ellipsoid(new ChEllipsoidShape);
    //	ellipsoid->GetEllipsoidGeometry().rad = size;
    //	ellipsoid->Pos = pos;
    //	ellipsoid->Rot = rot;
    //
    //	body->GetAssets().push_back(ellipsoid);

    //	chrono::utils::AddCapsuleGeometry(body.get_ptr(), size.x, size.y);		// X
    //	chrono::utils::AddCylinderGeometry(body.get_ptr(), size.x, size.y);		// O
    //	chrono::utils::AddConeGeometry(body.get_ptr(), size.x, size.y); 		// X
    //	chrono::utils::AddBoxGeometry(body.get_ptr(), size);					// O
    chrono::utils::AddSphereGeometry(body.get_ptr(), rad);  // O
                                                    //	chrono::utils::AddEllipsoidGeometry(body.get_ptr(), size);					// X

    body->GetCollisionModel()->SetFamily(collisionFamilly);
    body->GetCollisionModel()->SetFamilyMaskNoCollisionWithFamily(collisionFamilly);

    body->GetCollisionModel()->BuildModel();
    mphysicalSystem.AddBody(body);
  }
}
//------------------------------------------------------------------------------------
void AddHydroForce(chrono::ChSystemParallelDVI& mphysicalSystem,
                          int& startIndexSph,
                          const NumberOfObjects& numObjects) {
  // openmp does not work here
	std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
	for (int i = 0; i < numObjects.numFluidMarkers; i++) {
		char forceTag[] = "hydrodynamics_force";
		chrono::ChSharedPtr<chrono::ChForce> hydroForce = (*(bodyIter + i))->SearchForce(forceTag);
		if (hydroForce.IsNull()) {
			hydroForce = chrono::ChSharedPtr<chrono::ChForce>(new chrono::ChForce);
			hydroForce->SetMode(
			  FTYPE_FORCE);  // no need for this. It is the default option.
			(*(bodyIter + i))->AddForce(hydroForce);
			// ** or: hydroForce = ChSharedPtr<ChForce>(new ChForce());
			hydroForce->SetName(forceTag);
		}
	}
}
//------------------------------------------------------------------------------------
void UpdateSphDataInChSystem(chrono::ChSystemParallelDVI& mphysicalSystem,
                             const thrust::host_vector<Real3>& posRadH,
                             const thrust::host_vector<Real4>& velMasH,
                             const NumberOfObjects& numObjects,
                             int startIndexSph) {
#pragma omp parallel for
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    Real3 p3 = posRadH[i];
    Real4 vM4 = velMasH[i];
    chrono::ChVector<> pos = chrono::ChVector<>(p3.x, p3.y, p3.z);
    chrono::ChVector<> vel = chrono::ChVector<>(vM4.x, vM4.y, vM4.z);

    int chSystemBodyId = startIndexSph + i;
    std::vector<chrono::ChBody*>::iterator ibody = mphysicalSystem.Get_bodylist()->begin() + chSystemBodyId;
    (*ibody)->SetPos(pos);
    (*ibody)->SetPos_dt(vel);
  }
}
//------------------------------------------------------------------------------------
void AddChSystemForcesToSphForces(thrust::host_vector<Real4>& derivVelRhoChronoH,
                                  const thrust::host_vector<Real4>& velMasH2,
                                  chrono::ChSystemParallelDVI& mphysicalSystem,
                                  const NumberOfObjects& numObjects,
                                  int startIndexSph,
                                  Real dT) {
  std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    chrono::ChVector<> v = ((chrono::ChBody*)(*(bodyIter + i)))->GetPos_dt();
    Real3 a3 = (mR3(v.x, v.y, v.z) - mR3(velMasH2[i])) / dT;  // f = m * a
    derivVelRhoChronoH[i] += mR4(a3, 0);                      // note, gravity force is also coming from rigid system
  }
}
//------------------------------------------------------------------------------------

void ClearArraysH(thrust::host_vector<Real3>& posRadH,  // do not set the size here since you are using push back later
                  thrust::host_vector<Real4>& velMasH,
                  thrust::host_vector<Real4>& rhoPresMuH) {
  posRadH.clear();
  velMasH.clear();
  rhoPresMuH.clear();
}
//------------------------------------------------------------------------------------

void ClearArraysH(thrust::host_vector<Real3>& posRadH,  // do not set the size here since you are using push back later
                  thrust::host_vector<Real4>& velMasH,
                  thrust::host_vector<Real4>& rhoPresMuH,
                  thrust::host_vector<uint>& bodyIndex,
                  thrust::host_vector<::int3>& referenceArray) {
  ClearArraysH(posRadH, velMasH, rhoPresMuH);
  bodyIndex.clear();
  referenceArray.clear();
}
//------------------------------------------------------------------------------------

void CopyD2H(thrust::host_vector<Real4>& derivVelRhoChronoH, const thrust::device_vector<Real4>& derivVelRhoD) {
  assert(derivVelRhoChronoH.size() == derivVelRhoD.size() && "Error! size mismatch host and device");
  thrust::copy(derivVelRhoD.begin(), derivVelRhoD.end(), derivVelRhoChronoH.begin());
}

//------------------------------------------------------------------------------------
void CountNumContactsPerSph(thrust::host_vector<short int>& numContactsOnAllSph,
                                  const chrono::ChSystemParallelDVI& mphysicalSystem,
                                  const NumberOfObjects& numObjects,
                                  int startIndexSph) {
	int numContacts = mphysicalSystem.data_manager->host_data.bids_rigid_rigid.size();
#pragma omp parallel for
	for (int i = 0; i < numContacts; i ++) {
		chrono::int2 ids = mphysicalSystem.data_manager->host_data.bids_rigid_rigid[i];
		if (ids.x > startIndexSph)
			numContactsOnAllSph[ids.x - startIndexSph] += 1;
		if (ids.y > startIndexSph)
			numContactsOnAllSph[ids.y - startIndexSph] += 1;
	}
}

//------------------------------------------------------------------------------------
void CopyForceSphToChSystem(chrono::ChSystemParallelDVI& mphysicalSystem,
		const NumberOfObjects& numObjects,
		int startIndexSph,
		const thrust::device_vector<Real4>& derivVelRhoD,
		const thrust::host_vector<short int>& numContactsOnAllSph,
		Real sphMass) {

	std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
	for (int i = 0; i < numObjects.numFluidMarkers; i++) {
		char forceTag[] = "hydrodynamics_force";
		chrono::ChSharedPtr<chrono::ChForce> hydroForce = (*(bodyIter + i))->SearchForce(forceTag);
//		if (!hydroForce.IsNull())
//			hydroForce->SetMforce(0);
//
//		if (numContactsOnAllSph[i] == 0) continue;
		assert(!hydroForce.IsNull() && "Error! sph marker does not have hyroforce tag in ChSystem");

		Real4 mDerivVelRho= derivVelRhoD[i];
		Real3 forceSphMarker = mR3(mDerivVelRho) * sphMass;
		chrono::ChVector<> f3 = chrono::ChVector<>(forceSphMarker.x, forceSphMarker.y, forceSphMarker.z);
		hydroForce->SetMforce(f3.Length());
		f3.Normalize();
		hydroForce->SetDir(f3);
	}
}

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

void CopyCustomChSystemPosVel2HostThrust(
        thrust::host_vector<Real3>& posRadH,
        thrust::host_vector<Real4>& velMasH,
		chrono::ChSystemParallelDVI& mphysicalSystem,
		const NumberOfObjects& numObjects,
		int startIndexSph,
		const thrust::host_vector<short int>& numContactsOnAllSph) {

	std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
	for (int i = 0; i < numObjects.numFluidMarkers; i++) {
		if (numContactsOnAllSph[i] == 0) continue;
		chrono::ChVector<> pos = (*(bodyIter + i))->GetPos();
		posRadH[i] = mR3(pos.x, pos.y, pos.z);
		chrono::ChVector<> vel = (*(bodyIter + i))->GetPos_dt();
		Real mass = velMasH[i].w;
		velMasH[i] = mR4(vel.x, vel.y, vel.z, mass);
	}
}
//------------------------------------------------------------------------------------

void CopyH2DPosVel(
		thrust::device_vector<Real3>& posRadD,
		thrust::device_vector<Real4>& velMasD,
		const thrust::host_vector<Real3>& posRadH,
		const thrust::host_vector<Real4>& velMasH) {
  assert(posRadH.size() == posRadD.size() && "Error! size mismatch host and device");
  thrust::copy(posRadH.begin(), posRadH.end(), posRadD.begin());
  thrust::copy(velMasH.begin(), velMasH.end(), velMasD.begin());
}

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

void CopyD2HPosVel(
		thrust::host_vector<Real3>& posRadH,
		thrust::host_vector<Real4>& velMasH,
		const thrust::host_vector<Real3>& posRadD,
		const thrust::host_vector<Real4>& velMasD) {
  assert(posRadH.size() == posRadD.size() && "Error! size mismatch host and device");
  thrust::copy(posRadD.begin(), posRadD.end(), posRadH.begin());
  thrust::copy(velMasD.begin(), velMasD.end(), velMasH.begin());
}

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

void CopyH2D(thrust::device_vector<Real4>& derivVelRhoD, const thrust::host_vector<Real4>& derivVelRhoChronoH) {
  assert(derivVelRhoChronoH.size() == derivVelRhoD.size() && "Error! size mismatch host and device");
  thrust::copy(derivVelRhoChronoH.begin(), derivVelRhoChronoH.end(), derivVelRhoD.begin());
}
//------------------------------------------------------------------------------------

void CopySys2D(thrust::device_vector<Real3>& posRadD,
               chrono::ChSystemParallelDVI& mphysicalSystem,
               const NumberOfObjects& numObjects,
               int startIndexSph) {
  thrust::host_vector<Real3> posRadH(numObjects.numFluidMarkers);
  std::vector<chrono::ChBody*>::iterator bodyIter = mphysicalSystem.Get_bodylist()->begin() + startIndexSph;
#pragma omp parallel for
  for (int i = 0; i < numObjects.numFluidMarkers; i++) {
    chrono::ChVector<> p = ((chrono::ChBody*)(*(bodyIter + i)))->GetPos();
    posRadH[i] += mR3(p.x, p.y, p.z);
  }
  thrust::copy(posRadH.begin(), posRadH.end(), posRadD.begin());
}
//------------------------------------------------------------------------------------

void CopyD2H(thrust::host_vector<Real3>& posRadH,  // do not set the size here since you are using push back later
             thrust::host_vector<Real4>& velMasH,
             thrust::host_vector<Real4>& rhoPresMuH,
             const thrust::device_vector<Real3>& posRadD,
             const thrust::device_vector<Real4>& velMasD,
             const thrust::device_vector<Real4>& rhoPresMuD) {
  assert(posRadH.size() == posRadD.size() && "Error! size mismatch host and device");
  thrust::copy(posRadD.begin(), posRadD.end(), posRadH.begin());
  thrust::copy(velMasD.begin(), velMasD.end(), velMasH.begin());
  thrust::copy(rhoPresMuD.begin(), rhoPresMuD.end(), rhoPresMuH.begin());
}
<|endoftext|>


<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 "query_optimizer/rules/Partition.hpp"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>

#include "query_optimizer/OptimizerContext.hpp"
#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp"
#include "query_optimizer/expressions/AttributeReference.hpp"
#include "query_optimizer/expressions/ExprId.hpp"
#include "query_optimizer/expressions/ExpressionUtil.hpp"
#include "query_optimizer/expressions/NamedExpression.hpp"
#include "query_optimizer/expressions/PatternMatcher.hpp"
#include "query_optimizer/physical/HashJoin.hpp"
#include "query_optimizer/physical/PartitionSchemeHeader.hpp"
#include "query_optimizer/physical/PatternMatcher.hpp"
#include "query_optimizer/physical/Physical.hpp"
#include "query_optimizer/physical/PhysicalType.hpp"
#include "query_optimizer/physical/Selection.hpp"
#include "query_optimizer/physical/TableReference.hpp"
#include "query_optimizer/physical/TopLevelPlan.hpp"
#include "utility/Cast.hpp"
#include "utility/EqualsAnyConstant.hpp"

#include "gflags/gflags.h"
#include "glog/logging.h"

using std::make_unique;
using std::move;
using std::size_t;
using std::static_pointer_cast;
using std::unordered_set;
using std::vector;

namespace quickstep {
namespace optimizer {

namespace E = expressions;
namespace P = physical;

static bool ValidateNumRepartitions(const char *flagname, std::uint64_t value) {
  return value > 1u;
}
DEFINE_uint64(num_repartitions, 4, "Number of repartitions for a join.");
static const volatile bool num_repartitions_dummy
    = gflags::RegisterFlagValidator(&FLAGS_num_repartitions, &ValidateNumRepartitions);

void Partition::init(const P::PhysicalPtr &input) {
  P::TopLevelPlanPtr top_level_plan;
  CHECK(P::SomeTopLevelPlan::MatchesWithConditionalCast(input, &top_level_plan));

  cost_model_ = make_unique<cost::StarSchemaSimpleCostModel>(top_level_plan->shared_subplans());
}

namespace {

bool needsSelection(const P::PhysicalType physical_type) {
  return QUICKSTEP_EQUALS_ANY_CONSTANT(physical_type,
                                       P::PhysicalType::kSharedSubplanReference,
                                       P::PhysicalType::kSort,
                                       P::PhysicalType::kTableReference,
                                       P::PhysicalType::kUnionAll);
}

P::PhysicalPtr Repartition(const P::PhysicalPtr &node, const vector<E::AttributeReferencePtr> &join_attributes,
                           const size_t num_partitions) {
  P::PartitionSchemeHeader::PartitionExprIds repartition_expr_ids;
  for (const E::AttributeReferencePtr &attr : join_attributes) {
    repartition_expr_ids.push_back({ attr->id() });
  }
  auto repartition_scheme_header = make_unique<P::PartitionSchemeHeader>(
      P::PartitionSchemeHeader::PartitionType::kHash, num_partitions, move(repartition_expr_ids));

  if (needsSelection(node->getPhysicalType())) {
    // Add a Selection node.
    return P::Selection::Create(node,
                                CastSharedPtrVector<E::NamedExpression>(node->getOutputAttributes()),
                                nullptr /* filter_predicate */, repartition_scheme_header.release());
  } else {
    // Overwrite the output partition scheme header of the node.
    return node->copyWithNewOutputPartitionSchemeHeader(repartition_scheme_header.release());
  }
}

}  // namespace

P::PhysicalPtr Partition::applyToNode(const P::PhysicalPtr &node) {
  // Will be used for aggregations.
  (void) optimizer_context_;

  switch (node->getPhysicalType()) {
    case P::PhysicalType::kHashJoin: {
      const P::HashJoinPtr hash_join = static_pointer_cast<const P::HashJoin>(node);

      P::PhysicalPtr left = hash_join->left();
      const P::PartitionSchemeHeader *left_partition_scheme_header =
          left->getOutputPartitionSchemeHeader();

      P::PhysicalPtr right = hash_join->right();
      const P::PartitionSchemeHeader *right_partition_scheme_header =
          right->getOutputPartitionSchemeHeader();

      if (!left_partition_scheme_header && !right_partition_scheme_header) {
        break;
      }

      const auto &left_join_attributes = hash_join->left_join_attributes();
      const auto &right_join_attributes = hash_join->right_join_attributes();

      bool left_needs_repartition = false;
      bool right_needs_repartition = false;
      size_t num_partitions = 1u;

      needsRepartitionForHashJoin(left_partition_scheme_header, left_join_attributes,
                                  right_partition_scheme_header, right_join_attributes,
                                  &left_needs_repartition, &right_needs_repartition, &num_partitions);
      // Repartition.
      if (left_needs_repartition) {
        left = Repartition(left, left_join_attributes, num_partitions);
      }

      if (right_needs_repartition) {
        right = Repartition(right, right_join_attributes, num_partitions);
      }

      unordered_set<E::ExprId> project_expr_ids;
      for (const E::AttributeReferencePtr &project_expression : hash_join->getOutputAttributes()) {
        project_expr_ids.insert(project_expression->id());
      }

      P::PartitionSchemeHeader::PartitionExprIds output_repartition_expr_ids;
      for (size_t i = 0; i < left_join_attributes.size(); ++i) {
        const E::ExprId left_join_id = left_join_attributes[i]->id();
        const E::ExprId right_join_id = right_join_attributes[i]->id();

        output_repartition_expr_ids.emplace_back();

        if (project_expr_ids.count(left_join_id)) {
          output_repartition_expr_ids.back().insert(left_join_id);
        }

        if (project_expr_ids.count(right_join_id)) {
          output_repartition_expr_ids.back().insert(right_join_id);
        }

        if (output_repartition_expr_ids.back().empty()) {
          // Some partition attribute will be projected out, so we use
          // the input partition id as the output partition id.
          output_repartition_expr_ids.clear();
          break;
        }
      }
      auto output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(
          P::PartitionSchemeHeader::PartitionType::kHash, num_partitions, move(output_repartition_expr_ids));
      if (left_needs_repartition || right_needs_repartition) {
        return P::HashJoin::Create(left, right, left_join_attributes, right_join_attributes,
                                   hash_join->residual_predicate(),
                                   hash_join->project_expressions(),
                                   hash_join->join_type(),
                                   output_partition_scheme_header.release());
      } else if (left_partition_scheme_header) {
        return hash_join->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
      }
      break;
    }
    case P::PhysicalType::kSelection: {
      const P::SelectionPtr selection = static_pointer_cast<const P::Selection>(node);

      const P::PartitionSchemeHeader *input_partition_scheme_header =
          selection->input()->getOutputPartitionSchemeHeader();
      if (input_partition_scheme_header && input_partition_scheme_header->isHashPartition()) {
        unordered_set<E::ExprId> project_expr_ids;
        for (const E::AttributeReferencePtr &project_expression : selection->getOutputAttributes()) {
          project_expr_ids.insert(project_expression->id());
        }

        const auto &input_partition_expr_ids = input_partition_scheme_header->partition_expr_ids;
        P::PartitionSchemeHeader::PartitionExprIds output_partition_expr_ids;
        for (const auto &equivalent_expr_ids : input_partition_expr_ids) {
          P::PartitionSchemeHeader::EquivalentPartitionExprIds output_equivalent_partition_expr_ids;
          for (const E::ExprId expr_id : equivalent_expr_ids) {
            if (project_expr_ids.find(expr_id) != project_expr_ids.end()) {
              output_equivalent_partition_expr_ids.insert(expr_id);
            }
          }

          if (!output_equivalent_partition_expr_ids.empty()) {
            output_partition_expr_ids.push_back(move(output_equivalent_partition_expr_ids));
          }
        }

        if (input_partition_expr_ids != output_partition_expr_ids) {
          auto output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(
              P::PartitionSchemeHeader::PartitionType::kHash,
              input_partition_scheme_header->num_partitions,
              move(output_partition_expr_ids));
          return selection->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
        }
      }
      break;
    }
    default:
      break;
  }
  return node;
}

void Partition::needsRepartitionForHashJoin(
    const P::PartitionSchemeHeader *left_partition_scheme_header,
    const vector<E::AttributeReferencePtr> &left_join_attributes,
    const P::PartitionSchemeHeader *right_partition_scheme_header,
    const vector<E::AttributeReferencePtr> &right_join_attributes,
    bool *left_needs_repartition,
    bool *right_needs_repartition,
    size_t *num_partitions) {
  DCHECK(left_partition_scheme_header || right_partition_scheme_header);

  *left_needs_repartition = false;
  *num_partitions = 1u;

  if (left_partition_scheme_header) {
    *num_partitions = left_partition_scheme_header->num_partitions;

    // Need to repartition unless the partition attributes are as the same as
    // the join attributes.
    *left_needs_repartition = true;
    if (left_partition_scheme_header->isHashPartition()) {
      unordered_set<E::ExprId> left_join_expr_ids;
      for (const E::AttributeReferencePtr &attr : left_join_attributes) {
        left_join_expr_ids.insert(attr->id());
      }

      if (left_partition_scheme_header->reusablePartitionScheme(left_join_expr_ids)) {
        *left_needs_repartition = false;
        *num_partitions = left_partition_scheme_header->num_partitions;
      }
    }
  } else if (right_partition_scheme_header) {
    *left_needs_repartition = true;
    *num_partitions = right_partition_scheme_header->num_partitions;
  }

  *right_needs_repartition = false;
  if (right_partition_scheme_header) {
    // Need to repartition unless the partition attributes are as the same as
    // the join attributes.
    *right_needs_repartition = true;
    if (right_partition_scheme_header->isHashPartition()) {
      unordered_set<E::ExprId> right_join_expr_ids;
      for (const E::AttributeReferencePtr &attr : right_join_attributes) {
        right_join_expr_ids.insert(attr->id());
      }

      if (right_partition_scheme_header->reusablePartitionScheme(right_join_expr_ids) &&
          (*left_needs_repartition || *num_partitions == right_partition_scheme_header->num_partitions)) {
        *right_needs_repartition = false;
        *num_partitions = right_partition_scheme_header->num_partitions;
      }
    }
  } else if (*left_needs_repartition) {
    // TODO(quickstep-team): use a cost model to choose the broadcast hash join
    // or repartitioned hash join if the right side has no partitions while the
    // left side needs to repartition. For now, we always use the latter.
    *right_needs_repartition = true;
  }

  if (*right_needs_repartition && *left_needs_repartition) {
    *num_partitions = FLAGS_num_repartitions;
  }

  DCHECK_NE(1u, *num_partitions);
}

}  // namespace optimizer
}  // namespace quickstep
<commit_msg>Minor style fixes in Partition rule.<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 "query_optimizer/rules/Partition.hpp"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>

#include "query_optimizer/OptimizerContext.hpp"
#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp"
#include "query_optimizer/expressions/AttributeReference.hpp"
#include "query_optimizer/expressions/ExprId.hpp"
#include "query_optimizer/expressions/ExpressionUtil.hpp"
#include "query_optimizer/expressions/NamedExpression.hpp"
#include "query_optimizer/expressions/PatternMatcher.hpp"
#include "query_optimizer/physical/HashJoin.hpp"
#include "query_optimizer/physical/PartitionSchemeHeader.hpp"
#include "query_optimizer/physical/PatternMatcher.hpp"
#include "query_optimizer/physical/Physical.hpp"
#include "query_optimizer/physical/PhysicalType.hpp"
#include "query_optimizer/physical/Selection.hpp"
#include "query_optimizer/physical/TableReference.hpp"
#include "query_optimizer/physical/TopLevelPlan.hpp"
#include "utility/Cast.hpp"
#include "utility/EqualsAnyConstant.hpp"

#include "gflags/gflags.h"
#include "glog/logging.h"

using std::make_unique;
using std::move;
using std::size_t;
using std::static_pointer_cast;
using std::unordered_set;
using std::vector;

namespace quickstep {
namespace optimizer {

namespace E = expressions;
namespace P = physical;

static bool ValidateNumRepartitions(const char *flagname, std::uint64_t value) {
  return value > 1u;
}
DEFINE_uint64(num_repartitions, 4, "Number of repartitions for a join.");
static const volatile bool num_repartitions_dummy
    = gflags::RegisterFlagValidator(&FLAGS_num_repartitions, &ValidateNumRepartitions);

void Partition::init(const P::PhysicalPtr &input) {
  P::TopLevelPlanPtr top_level_plan;
  CHECK(P::SomeTopLevelPlan::MatchesWithConditionalCast(input, &top_level_plan));

  cost_model_ = make_unique<cost::StarSchemaSimpleCostModel>(top_level_plan->shared_subplans());
}

namespace {

bool needsSelection(const P::PhysicalType physical_type) {
  return QUICKSTEP_EQUALS_ANY_CONSTANT(physical_type,
                                       P::PhysicalType::kSharedSubplanReference,
                                       P::PhysicalType::kSort,
                                       P::PhysicalType::kTableReference,
                                       P::PhysicalType::kUnionAll);
}

P::PhysicalPtr HashRepartition(const P::PhysicalPtr &node,
                               const vector<E::AttributeReferencePtr> &repartition_attributes,
                               const size_t num_repartitions) {
  P::PartitionSchemeHeader::PartitionExprIds repartition_expr_ids;
  for (const E::AttributeReferencePtr &attr : repartition_attributes) {
    repartition_expr_ids.push_back({ attr->id() });
  }
  auto repartition_scheme_header = make_unique<P::PartitionSchemeHeader>(
      P::PartitionSchemeHeader::PartitionType::kHash, num_repartitions, move(repartition_expr_ids));

  if (needsSelection(node->getPhysicalType())) {
    // Add a Selection node.
    return P::Selection::Create(node,
                                CastSharedPtrVector<E::NamedExpression>(node->getOutputAttributes()),
                                nullptr /* filter_predicate */, repartition_scheme_header.release());
  } else {
    // Overwrite the output partition scheme header of the node.
    return node->copyWithNewOutputPartitionSchemeHeader(repartition_scheme_header.release());
  }
}

}  // namespace

P::PhysicalPtr Partition::applyToNode(const P::PhysicalPtr &node) {
  // Will be used for aggregations.
  (void) optimizer_context_;

  switch (node->getPhysicalType()) {
    case P::PhysicalType::kHashJoin: {
      const P::HashJoinPtr hash_join = static_pointer_cast<const P::HashJoin>(node);

      P::PhysicalPtr left = hash_join->left();
      const P::PartitionSchemeHeader *left_partition_scheme_header =
          left->getOutputPartitionSchemeHeader();

      P::PhysicalPtr right = hash_join->right();
      const P::PartitionSchemeHeader *right_partition_scheme_header =
          right->getOutputPartitionSchemeHeader();

      if (!left_partition_scheme_header && !right_partition_scheme_header) {
        break;
      }

      const auto &left_join_attributes = hash_join->left_join_attributes();
      const auto &right_join_attributes = hash_join->right_join_attributes();

      bool left_needs_repartition = false;
      bool right_needs_repartition = false;
      size_t num_partitions = 1u;

      needsRepartitionForHashJoin(left_partition_scheme_header, left_join_attributes,
                                  right_partition_scheme_header, right_join_attributes,
                                  &left_needs_repartition, &right_needs_repartition, &num_partitions);
      // Hash repartition.
      if (left_needs_repartition) {
        left = HashRepartition(left, left_join_attributes, num_partitions);
      }

      if (right_needs_repartition) {
        right = HashRepartition(right, right_join_attributes, num_partitions);
      }

      unordered_set<E::ExprId> project_expr_ids;
      for (const E::AttributeReferencePtr &project_expression : hash_join->getOutputAttributes()) {
        project_expr_ids.insert(project_expression->id());
      }

      P::PartitionSchemeHeader::PartitionExprIds output_repartition_expr_ids;
      for (size_t i = 0; i < left_join_attributes.size(); ++i) {
        const E::ExprId left_join_id = left_join_attributes[i]->id();
        const E::ExprId right_join_id = right_join_attributes[i]->id();

        output_repartition_expr_ids.emplace_back();

        if (project_expr_ids.count(left_join_id)) {
          output_repartition_expr_ids.back().insert(left_join_id);
        }

        if (project_expr_ids.count(right_join_id)) {
          output_repartition_expr_ids.back().insert(right_join_id);
        }

        if (output_repartition_expr_ids.back().empty()) {
          // Some partition attribute will be projected out, so we use
          // the input partition id as the output partition id.
          output_repartition_expr_ids.clear();
          break;
        }
      }
      auto output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(
          P::PartitionSchemeHeader::PartitionType::kHash, num_partitions, move(output_repartition_expr_ids));
      if (left_needs_repartition || right_needs_repartition) {
        return P::HashJoin::Create(left, right, left_join_attributes, right_join_attributes,
                                   hash_join->residual_predicate(),
                                   hash_join->project_expressions(),
                                   hash_join->join_type(),
                                   output_partition_scheme_header.release());
      } else if (left_partition_scheme_header) {
        return hash_join->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
      }
      break;
    }
    case P::PhysicalType::kSelection: {
      const P::SelectionPtr selection = static_pointer_cast<const P::Selection>(node);

      const P::PartitionSchemeHeader *input_partition_scheme_header =
          selection->input()->getOutputPartitionSchemeHeader();
      if (input_partition_scheme_header && input_partition_scheme_header->isHashPartition()) {
        unordered_set<E::ExprId> project_expr_ids;
        for (const E::AttributeReferencePtr &project_expression : selection->getOutputAttributes()) {
          project_expr_ids.insert(project_expression->id());
        }

        const auto &input_partition_expr_ids = input_partition_scheme_header->partition_expr_ids;
        P::PartitionSchemeHeader::PartitionExprIds output_partition_expr_ids;
        for (const auto &equivalent_expr_ids : input_partition_expr_ids) {
          P::PartitionSchemeHeader::EquivalentPartitionExprIds output_equivalent_partition_expr_ids;
          for (const E::ExprId expr_id : equivalent_expr_ids) {
            if (project_expr_ids.find(expr_id) != project_expr_ids.end()) {
              output_equivalent_partition_expr_ids.insert(expr_id);
            }
          }

          if (!output_equivalent_partition_expr_ids.empty()) {
            output_partition_expr_ids.push_back(move(output_equivalent_partition_expr_ids));
          }
        }

        if (input_partition_expr_ids != output_partition_expr_ids) {
          auto output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(
              P::PartitionSchemeHeader::PartitionType::kHash,
              input_partition_scheme_header->num_partitions,
              move(output_partition_expr_ids));
          return selection->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
        }
      }
      break;
    }
    default:
      break;
  }
  return node;
}

void Partition::needsRepartitionForHashJoin(
    const P::PartitionSchemeHeader *left_partition_scheme_header,
    const vector<E::AttributeReferencePtr> &left_join_attributes,
    const P::PartitionSchemeHeader *right_partition_scheme_header,
    const vector<E::AttributeReferencePtr> &right_join_attributes,
    bool *left_needs_repartition,
    bool *right_needs_repartition,
    size_t *num_partitions) {
  DCHECK(left_partition_scheme_header || right_partition_scheme_header);

  *left_needs_repartition = false;
  *num_partitions = 1u;

  if (left_partition_scheme_header) {
    *num_partitions = left_partition_scheme_header->num_partitions;

    // Need to repartition unless the partition attributes are as the same as
    // the join attributes.
    *left_needs_repartition = true;
    if (left_partition_scheme_header->isHashPartition()) {
      unordered_set<E::ExprId> left_join_expr_ids;
      for (const E::AttributeReferencePtr &attr : left_join_attributes) {
        left_join_expr_ids.insert(attr->id());
      }

      if (left_partition_scheme_header->reusablePartitionScheme(left_join_expr_ids)) {
        *left_needs_repartition = false;
        *num_partitions = left_partition_scheme_header->num_partitions;
      }
    }
  } else if (right_partition_scheme_header) {
    *left_needs_repartition = true;
    *num_partitions = right_partition_scheme_header->num_partitions;
  }

  *right_needs_repartition = false;
  if (right_partition_scheme_header) {
    // Need to repartition unless the partition attributes are as the same as
    // the join attributes.
    *right_needs_repartition = true;
    if (right_partition_scheme_header->isHashPartition()) {
      unordered_set<E::ExprId> right_join_expr_ids;
      for (const E::AttributeReferencePtr &attr : right_join_attributes) {
        right_join_expr_ids.insert(attr->id());
      }

      if (right_partition_scheme_header->reusablePartitionScheme(right_join_expr_ids) &&
          (*left_needs_repartition || *num_partitions == right_partition_scheme_header->num_partitions)) {
        *right_needs_repartition = false;
        *num_partitions = right_partition_scheme_header->num_partitions;
      }
    }
  } else if (*left_needs_repartition) {
    // TODO(quickstep-team): use a cost model to choose the broadcast hash join
    // or repartitioned hash join if the right side has no partitions while the
    // left side needs to repartition. For now, we always use the latter.
    *right_needs_repartition = true;
  }

  if (*right_needs_repartition && *left_needs_repartition) {
    *num_partitions = FLAGS_num_repartitions;
  }

  DCHECK_NE(1u, *num_partitions);
}

}  // namespace optimizer
}  // namespace quickstep
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <functional>

// class function<R(ArgTypes...)>

// function(const function&  f);
// function(const function&& f);

#include <functional>
#include <memory>
#include <cstdlib>
#include <cassert>

#include "test_macros.h"
#include "count_new.hpp"

class A
{
    int data_[10];
public:
    static int count;

    A()
    {
        ++count;
        for (int i = 0; i < 10; ++i)
            data_[i] = i;
    }

    A(const A&) {++count;}

    ~A() {--count;}

    int operator()(int i) const
    {
        for (int j = 0; j < 10; ++j)
            i += data_[j];
        return i;
    }
};

int A::count = 0;

int g(int) {return 0;}

int main()
{
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
    std::function<int(int)> f = A();
    assert(A::count == 1);
    assert(globalMemCounter.checkOutstandingNewEq(1));
    assert(f.target<A>());
    assert(f.target<int(*)(int)>() == 0);
    std::function<int(int)> f2 = f;
    assert(A::count == 2);
    assert(globalMemCounter.checkOutstandingNewEq(2));
    assert(f2.target<A>());
    assert(f2.target<int(*)(int)>() == 0);
    }
    assert(A::count == 0);
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
    std::function<int(int)> f = g;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f.target<int(*)(int)>());
    assert(f.target<A>() == 0);
    std::function<int(int)> f2 = f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f2.target<int(*)(int)>());
    assert(f2.target<A>() == 0);
    }
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
    std::function<int(int)> f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f.target<int(*)(int)>() == 0);
    assert(f.target<A>() == 0);
    std::function<int(int)> f2 = f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f2.target<int(*)(int)>() == 0);
    assert(f2.target<A>() == 0);
    }
    {
    std::function<int(int)> f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f.target<int(*)(int)>() == 0);
    assert(f.target<A>() == 0);
    assert(!f);
    std::function<long(int)> g = f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(g.target<long(*)(int)>() == 0);
    assert(g.target<A>() == 0);
    assert(!g);
    }
#if TEST_STD_VER >= 11
    assert(globalMemCounter.checkOutstandingNewEq(0));
    { // Test rvalue references
        std::function<int(int)> f = A();
        assert(A::count == 1);
        assert(globalMemCounter.checkOutstandingNewEq(1));
        assert(f.target<A>());
        assert(f.target<int(*)(int)>() == 0);
        std::function<int(int)> f2 = std::move(f);
        assert(A::count == 1);
        assert(globalMemCounter.checkOutstandingNewEq(1));
        assert(f2.target<A>());
        assert(f2.target<int(*)(int)>() == 0);
        assert(f.target<A>() == 0);
        assert(f.target<int(*)(int)>() == 0);
    }
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
        // Test that moving a function constructed from a reference wrapper
        // is done without allocating.
        DisableAllocationGuard g;
        using Ref = std::reference_wrapper<A>;
        A a;
        Ref aref(a);
        std::function<int(int)> f(aref);
        assert(A::count == 1);
        assert(f.target<A>() == nullptr);
        assert(f.target<Ref>());
        std::function<int(int)> f2(std::move(f));
        assert(A::count == 1);
        assert(f2.target<A>() == nullptr);
        assert(f2.target<Ref>());
        LIBCPP_ASSERT(f.target<Ref>()); // f is unchanged because the target is small
    }
    {
        // Test that moving a function constructed from a function pointer
        // is done without allocating
        DisableAllocationGuard guard;
        using Ptr = int(*)(int);
        Ptr p = g;
        std::function<int(int)> f(p);
        assert(f.target<A>() == nullptr);
        assert(f.target<Ptr>());
        std::function<int(int)> f2(std::move(f));
        assert(f2.target<A>() == nullptr);
        assert(f2.target<Ptr>());
        LIBCPP_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small
    }
#endif  // TEST_STD_VER >= 11
}
<commit_msg>func.wrap.func.con: Fix test comment<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <functional>

// class function<R(ArgTypes...)>

// function(const function&  f);
// function(function&& f);

#include <functional>
#include <memory>
#include <cstdlib>
#include <cassert>

#include "test_macros.h"
#include "count_new.hpp"

class A
{
    int data_[10];
public:
    static int count;

    A()
    {
        ++count;
        for (int i = 0; i < 10; ++i)
            data_[i] = i;
    }

    A(const A&) {++count;}

    ~A() {--count;}

    int operator()(int i) const
    {
        for (int j = 0; j < 10; ++j)
            i += data_[j];
        return i;
    }
};

int A::count = 0;

int g(int) {return 0;}

int main()
{
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
    std::function<int(int)> f = A();
    assert(A::count == 1);
    assert(globalMemCounter.checkOutstandingNewEq(1));
    assert(f.target<A>());
    assert(f.target<int(*)(int)>() == 0);
    std::function<int(int)> f2 = f;
    assert(A::count == 2);
    assert(globalMemCounter.checkOutstandingNewEq(2));
    assert(f2.target<A>());
    assert(f2.target<int(*)(int)>() == 0);
    }
    assert(A::count == 0);
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
    std::function<int(int)> f = g;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f.target<int(*)(int)>());
    assert(f.target<A>() == 0);
    std::function<int(int)> f2 = f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f2.target<int(*)(int)>());
    assert(f2.target<A>() == 0);
    }
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
    std::function<int(int)> f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f.target<int(*)(int)>() == 0);
    assert(f.target<A>() == 0);
    std::function<int(int)> f2 = f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f2.target<int(*)(int)>() == 0);
    assert(f2.target<A>() == 0);
    }
    {
    std::function<int(int)> f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(f.target<int(*)(int)>() == 0);
    assert(f.target<A>() == 0);
    assert(!f);
    std::function<long(int)> g = f;
    assert(globalMemCounter.checkOutstandingNewEq(0));
    assert(g.target<long(*)(int)>() == 0);
    assert(g.target<A>() == 0);
    assert(!g);
    }
#if TEST_STD_VER >= 11
    assert(globalMemCounter.checkOutstandingNewEq(0));
    { // Test rvalue references
        std::function<int(int)> f = A();
        assert(A::count == 1);
        assert(globalMemCounter.checkOutstandingNewEq(1));
        assert(f.target<A>());
        assert(f.target<int(*)(int)>() == 0);
        std::function<int(int)> f2 = std::move(f);
        assert(A::count == 1);
        assert(globalMemCounter.checkOutstandingNewEq(1));
        assert(f2.target<A>());
        assert(f2.target<int(*)(int)>() == 0);
        assert(f.target<A>() == 0);
        assert(f.target<int(*)(int)>() == 0);
    }
    assert(globalMemCounter.checkOutstandingNewEq(0));
    {
        // Test that moving a function constructed from a reference wrapper
        // is done without allocating.
        DisableAllocationGuard g;
        using Ref = std::reference_wrapper<A>;
        A a;
        Ref aref(a);
        std::function<int(int)> f(aref);
        assert(A::count == 1);
        assert(f.target<A>() == nullptr);
        assert(f.target<Ref>());
        std::function<int(int)> f2(std::move(f));
        assert(A::count == 1);
        assert(f2.target<A>() == nullptr);
        assert(f2.target<Ref>());
        LIBCPP_ASSERT(f.target<Ref>()); // f is unchanged because the target is small
    }
    {
        // Test that moving a function constructed from a function pointer
        // is done without allocating
        DisableAllocationGuard guard;
        using Ptr = int(*)(int);
        Ptr p = g;
        std::function<int(int)> f(p);
        assert(f.target<A>() == nullptr);
        assert(f.target<Ptr>());
        std::function<int(int)> f2(std::move(f));
        assert(f2.target<A>() == nullptr);
        assert(f2.target<Ptr>());
        LIBCPP_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small
    }
#endif  // TEST_STD_VER >= 11
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mdialog.h"
#include "mdialog_p.h"

#include <mbuttonmodel.h>
#include <MDebug>
#include <MDismissEvent>
#include <MHomeButtonPanel>
#include <MLocale>
#include <MScene>
#include <MWindow>

#ifdef Q_WS_X11
#   include <QX11Info>
#   include <X11/Xlib.h>
#endif

#include <QSignalMapper>

#include <MApplication>
#include <MSceneManager>

#include "mwidgetcreator.h"
M_REGISTER_WIDGET(MDialog)

MDialogPrivate::MDialogPrivate()
    :
    clickedButton(0),
    buttonClickedMapper(0),
    dumbMode(false),
    standAloneWindow(0),
    homeButtonPanel(0),
    suicideAfterDestroyingStandAloneWindow(false)
{
}

MDialogPrivate::~MDialogPrivate()
{
    if (buttonClickedMapper) {
        delete buttonClickedMapper;
        buttonClickedMapper = 0;
    }

    if (standAloneWindow) {
        Q_Q(MDialog);
        standAloneWindow->scene()->removeItem(q);
        delete standAloneWindow;
        standAloneWindow = 0;
    }
}

void MDialogPrivate::init()
{
    Q_Q(MDialog);

    clickedButton = 0;

    q->setFocusPolicy(Qt::ClickFocus);
}

void MDialogPrivate::appear(MSceneWindow::DeletionPolicy policy)
{
    Q_Q(MDialog);
    MWindow *window;

    if (q->isSystemModal()) {
        if (prepareStandAloneAppearance(policy)) {
            q->appear(standAloneWindow);
        }
    } else {
        window = MApplication::activeWindow();
        if (window) {
            q->appear(window, policy);
        } else {
            mWarning("MDialog") << "Cannot appear. No MWindow currently active.";
        }
    }
}

void MDialogPrivate::addStandardButtons(M::StandardButtons standardButtons)
{
    Q_Q(MDialog);

    uint buttonFlag = M::FirstButton;
    while (buttonFlag <= M::LastButton) {
        if (standardButtons.testFlag((M::StandardButton)buttonFlag)) {
            q->model()->addButton((M::StandardButton)buttonFlag);
        }
        buttonFlag = buttonFlag << 1;
    }
}

void MDialogPrivate::_q_buttonClicked(QObject *obj)
{
    Q_Q(MDialog);
    MButtonModel *buttonModel = 0;

    buttonModel = qobject_cast<MButtonModel *>(obj);
    if (buttonModel) {
        clickedButton = buttonModel;
        int result = resultFromStandardButtonId(q->model()->standardButton(buttonModel));
        q->done(result);
    }
}

void MDialogPrivate::updateStandAloneHomeButtonVisibility()
{
    Q_Q(MDialog);

    if (q->isSystemModal()) {
        // Remove the home button if it's there.
        if (homeButtonPanel) {
            if (homeButtonPanel->scene() != 0) {
                Q_ASSERT(homeButtonPanel->scene() == standAloneWindow->scene());
                standAloneWindow->sceneManager()->disappearSceneWindowNow(homeButtonPanel);
            }

            delete homeButtonPanel;
            homeButtonPanel = 0;
        }
    } else {
        // Put a home button on the system modal window
        homeButtonPanel = new MHomeButtonPanel();

        standAloneWindow->connect(homeButtonPanel,
                                  SIGNAL(buttonClicked()), SLOT(showMinimized()));

        standAloneWindow->sceneManager()->appearSceneWindowNow(homeButtonPanel);
    }
}

void MDialogPrivate::_q_onStandAloneDialogDisappeared()
{
    Q_Q(MDialog);
    Q_ASSERT(standAloneWindow != 0);

    q->disconnect(SIGNAL(disappeared()), q, SLOT(_q_onStandAloneDialogDisappeared()));

    standAloneWindow->setScene(0);
    standAloneWindow->deleteLater();
    standAloneWindow = 0;

    // Remove dialog from scene otherwise scene will delete dialog
    // on scene's destructor
    if (q->scene()) {
        q->scene()->removeItem(q);
    }

    if (homeButtonPanel) {
        if (homeButtonPanel->sceneManager())
            homeButtonPanel->sceneManager()->disappearSceneWindowNow(homeButtonPanel);
        delete homeButtonPanel;
        homeButtonPanel = 0;
    }

    if (suicideAfterDestroyingStandAloneWindow) {
        q->deleteLater();
    }
}

bool MDialogPrivate::prepareStandAloneAppearance(MSceneWindow::DeletionPolicy policy)
{
    Q_Q(MDialog);
    bool ok = true;

    if (standAloneWindow == 0) {
        standAloneWindow = new MWindow(new MSceneManager);
        standAloneWindow->setTranslucentBackground(true);
#ifdef Q_WS_X11
        XSetTransientForHint(QX11Info::display(), standAloneWindow->winId(), MApplication::activeWindow()->winId());
#endif
        q->connect(q, SIGNAL(disappeared()), SLOT(_q_onStandAloneDialogDisappeared()));
    }

    // We only have a home button in the stand-alone window if the
    // the dialog is supposed to be modeless.
    updateStandAloneHomeButtonVisibility();

    // Dialog will handle its own deletion policy instead of scene manager
    // since in this case the dialog owns the scene manager and not the other
    // way around
    suicideAfterDestroyingStandAloneWindow = (policy == MSceneWindow::DestroyWhenDone);

    standAloneWindow->show();

    // Check whether the dialog is already present in some scene manager
    if (shown) {
        if (q->sceneManager() != standAloneWindow->sceneManager()) {
            q->sceneManager()->disappearSceneWindowNow(q);
        } else {
            ok = false;
        }
    }

    return ok;
}

void MDialogPrivate::updateButtonClickedMappings()
{
    Q_Q(MDialog);

    if (buttonClickedMapper) {
        delete buttonClickedMapper;
        buttonClickedMapper = 0;
    }

    buttonClickedMapper = new QSignalMapper();
    q->connect(buttonClickedMapper, SIGNAL(mapped(QObject *)),
               SLOT(_q_buttonClicked(QObject *)));

    MButtonModel *buttonModel;
    MDialogButtonsList buttonModelsList = q->model()->buttons();

    const int buttonModelsSize = buttonModelsList.size();
    for (int i = 0; i < buttonModelsSize; ++i) {
        buttonModel = buttonModelsList[i];

        buttonClickedMapper->connect(buttonModel, SIGNAL(clicked()), SLOT(map()));
        buttonClickedMapper->setMapping(buttonModel, buttonModel);
    }
}

int MDialogPrivate::resultFromStandardButtonId(int buttonId)
{
    switch (buttonId) {
    case M::NoStandardButton:
    case M::OkButton:
    case M::SaveButton:
    case M::SaveAllButton:
    case M::OpenButton:
    case M::YesButton:
    case M::YesToAllButton:
    case M::RetryButton:
    case M::ApplyButton:
    case M::DoneButton:
        return MDialog::Accepted;
    case M::NoButton:
    case M::NoToAllButton:
    case M::AbortButton:
    case M::IgnoreButton:
    case M::CloseButton:
    case M::CancelButton:
    case M::DiscardButton:
    case M::HelpButton:
    case M::ResetButton:
    case M::RestoreDefaultsButton:
        return MDialog::Rejected;
    default:
        //Non-standard buttons should be handled by NoStandardButton case.
        //This should not happen.
        return MDialog::Accepted;
    };
}

MDialog::MDialog() :
    MSceneWindow(new MDialogPrivate(), new MDialogModel(), MSceneWindow::Dialog, QString())
{
    Q_D(MDialog);

    d->init();

    model()->setResultCode(MDialog::Rejected);
}

MDialog::MDialog(const QString &title, M::StandardButtons buttons) :
    MSceneWindow(new MDialogPrivate(), new MDialogModel(), MSceneWindow::Dialog, QString())
{
    Q_D(MDialog);

    d->init();

    model()->setResultCode(MDialog::Rejected);

    setTitle(title);

    d->addStandardButtons(buttons);
}

MDialog::MDialog(MDialogPrivate *dd, MDialogModel *model, MSceneWindow::WindowType windowType) :
    MSceneWindow(dd, model, windowType, QString())
{
    Q_D(MDialog);

    d->init();

    model->setResultCode(MDialog::Rejected);
}

MDialog::MDialog(MDialogPrivate *dd, M::StandardButtons buttons,
                     MDialogModel *model, MSceneWindow::WindowType windowType) :
    MSceneWindow(dd, model, windowType, QString())
{
    Q_D(MDialog);

    d->init();

    model->setResultCode(MDialog::Rejected);

    d->addStandardButtons(buttons);
}

MDialog::~MDialog()
{
}

QString MDialog::title() const
{
    return model()->title();
}

void MDialog::setTitle(const QString &title)
{
    model()->setTitle(title);
}

QGraphicsWidget *MDialog::centralWidget()
{
    return model()->centralWidget();
}

void MDialog::setCentralWidget(QGraphicsWidget *centralWidget)
{
    if (model()->centralWidget())
        delete model()->centralWidget();

    model()->setCentralWidget(centralWidget);
}

void MDialog::addButton(MButtonModel *buttonModel)
{
    model()->addButton(buttonModel);
}

MButtonModel *MDialog::addButton(const QString &text)
{
    MButtonModel *buttonModel = 0;

    buttonModel = new MButtonModel;
    buttonModel->setText(text);
    model()->addButton(buttonModel);

    return buttonModel;
}

MButtonModel *MDialog::addButton(M::StandardButton buttonType)
{
    return model()->addButton(buttonType);
}

void MDialog::removeButton(MButtonModel *buttonModel)
{
    model()->removeButton(buttonModel);
}

MButtonModel *MDialog::button(M::StandardButton which)
{
    return model()->button(which);
}

M::StandardButton MDialog::standardButton(MButtonModel *buttonModel) const
{
    return model()->standardButton(buttonModel);
}

void MDialog::appear(MSceneWindow::DeletionPolicy policy)
{
    Q_D(MDialog);
    d->appear(policy);
}

void MDialog::appear(MWindow *window, MSceneWindow::DeletionPolicy policy)
{
    Q_D(MDialog);

    if (window) {
        MSceneWindow::appear(window, policy);
    } else {
        d->appear(policy);
    }
}

void MDialog::accept()
{
    done(Accepted);
}

void MDialog::reject()
{
    done(Rejected);
}

void MDialog::done(int result)
{
    setResult(result);

    emit finished(result);
    if (result == MDialog::Accepted)
        emit accepted();
    else if (result == MDialog::Rejected)
        emit rejected();

    if (sceneManager())
        sceneManager()->disappearSceneWindow(this);
}

int MDialog::exec(MWindow *window)
{
    Q_D(MDialog);
    MSceneManager *targetSceneManager = 0;
    int result;

    d->clickedButton = 0;
    d->policy = MSceneWindow::KeepWhenDone;

    if (window) {
        targetSceneManager = window->sceneManager();
    } else {
        if (isSystemModal()) {
            d->prepareStandAloneAppearance(KeepWhenDone);
            targetSceneManager = d->standAloneWindow->sceneManager();
        } else {
            window = MApplication::activeWindow();
            if (window) {
                targetSceneManager = window->sceneManager();
            } else {
                mWarning("MDialog") << "Cannot appear. No MWindow currently active.";
            }
        }
    }

    if (targetSceneManager) {
        result = targetSceneManager->execDialog(this);
    } else {
        result = Rejected;
    }

    return result;
}

MButtonModel *MDialog::clickedButton() const
{
    Q_D(const MDialog);

    return d->clickedButton;
}

int MDialog::result() const
{
    return model()->resultCode();
}

void MDialog::setResult(int result)
{
    model()->setResultCode(result);
}

bool MDialog::isButtonBoxVisible() const
{
    return model()->buttonBoxVisible();
}

void MDialog::setButtonBoxVisible(bool visible)
{
    model()->setButtonBoxVisible(visible);
}

bool MDialog::isCloseButtonVisible() const
{
    return model()->closeButtonVisible();
}

void MDialog::setCloseButtonVisible(bool visible)
{
    model()->setCloseButtonVisible(visible);
}

bool MDialog::isProgressIndicatorVisible() const
{
    return model()->progressIndicatorVisible();
}

void MDialog::setProgressIndicatorVisible(bool visible)
{
    model()->setProgressIndicatorVisible(visible);
}

bool MDialog::isTitleBarVisible() const
{
    return model()->titleBarVisible();
}

void MDialog::setTitleBarVisible(bool visible)
{
    model()->setTitleBarVisible(visible);
}

bool MDialog::isSystemModal() const
{
    return model()->systemModal();
}

void MDialog::setSystemModal(bool systemModal)
{
    model()->setSystemModal(systemModal);
}

void MDialog::setLayout(QGraphicsLayout *layout)
{
    Q_D(MDialog);
    mWarning("MDialog:") << "Please don't change the layout directly.";
    d->dumbMode = true;
    QGraphicsWidget::setLayout(layout);
}

QGraphicsLayout *MDialog::layout()
{
    Q_D(MDialog);
    mWarning("MDialog:") << "Please don't change the layout directly.";
    d->dumbMode = true;
    return QGraphicsWidget::layout();
}

void MDialog::updateData(const QList<const char *>& modifications)
{
    MSceneWindow::updateData(modifications);
    Q_D(MDialog);

    if (modifications.contains(MDialogModel::Buttons)) {
        d->updateButtonClickedMappings();
        d->clickedButton = 0;
    }
}

void MDialog::setupModel()
{
    MSceneWindow::setupModel();
    Q_D(MDialog);
    d->updateButtonClickedMappings();
    d->clickedButton = 0;
}

void MDialog::dismissEvent(MDismissEvent *event)
{
    setResult(Rejected);
    emit finished(result());
    emit rejected();

    event->accept();
}

#include "moc_mdialog.cpp"
<commit_msg>Fixes: NB#164608 - System modal dialogs do not set the _NET_WM_WINDOW_TYPE_DIALOG window hint<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mdialog.h"
#include "mdialog_p.h"

#include <mbuttonmodel.h>
#include <MDebug>
#include <MDismissEvent>
#include <MHomeButtonPanel>
#include <MLocale>
#include <MScene>
#include <MWindow>

#ifdef Q_WS_X11
#   include <QX11Info>
#   include <X11/Xlib.h>
#endif

#include <QSignalMapper>

#include <MApplication>
#include <MSceneManager>

#include "mwidgetcreator.h"
M_REGISTER_WIDGET(MDialog)

MDialogPrivate::MDialogPrivate()
    :
    clickedButton(0),
    buttonClickedMapper(0),
    dumbMode(false),
    standAloneWindow(0),
    homeButtonPanel(0),
    suicideAfterDestroyingStandAloneWindow(false)
{
}

MDialogPrivate::~MDialogPrivate()
{
    if (buttonClickedMapper) {
        delete buttonClickedMapper;
        buttonClickedMapper = 0;
    }

    if (standAloneWindow) {
        Q_Q(MDialog);
        standAloneWindow->scene()->removeItem(q);
        delete standAloneWindow;
        standAloneWindow = 0;
    }
}

void MDialogPrivate::init()
{
    Q_Q(MDialog);

    clickedButton = 0;

    q->setFocusPolicy(Qt::ClickFocus);
}

void MDialogPrivate::appear(MSceneWindow::DeletionPolicy policy)
{
    Q_Q(MDialog);
    MWindow *window;

    if (q->isSystemModal()) {
        if (prepareStandAloneAppearance(policy)) {
            q->appear(standAloneWindow);
        }
    } else {
        window = MApplication::activeWindow();
        if (window) {
            q->appear(window, policy);
        } else {
            mWarning("MDialog") << "Cannot appear. No MWindow currently active.";
        }
    }
}

void MDialogPrivate::addStandardButtons(M::StandardButtons standardButtons)
{
    Q_Q(MDialog);

    uint buttonFlag = M::FirstButton;
    while (buttonFlag <= M::LastButton) {
        if (standardButtons.testFlag((M::StandardButton)buttonFlag)) {
            q->model()->addButton((M::StandardButton)buttonFlag);
        }
        buttonFlag = buttonFlag << 1;
    }
}

void MDialogPrivate::_q_buttonClicked(QObject *obj)
{
    Q_Q(MDialog);
    MButtonModel *buttonModel = 0;

    buttonModel = qobject_cast<MButtonModel *>(obj);
    if (buttonModel) {
        clickedButton = buttonModel;
        int result = resultFromStandardButtonId(q->model()->standardButton(buttonModel));
        q->done(result);
    }
}

void MDialogPrivate::updateStandAloneHomeButtonVisibility()
{
    Q_Q(MDialog);

    if (q->isSystemModal()) {
        // Remove the home button if it's there.
        if (homeButtonPanel) {
            if (homeButtonPanel->scene() != 0) {
                Q_ASSERT(homeButtonPanel->scene() == standAloneWindow->scene());
                standAloneWindow->sceneManager()->disappearSceneWindowNow(homeButtonPanel);
            }

            delete homeButtonPanel;
            homeButtonPanel = 0;
        }
    } else {
        // Put a home button on the system modal window
        homeButtonPanel = new MHomeButtonPanel();

        standAloneWindow->connect(homeButtonPanel,
                                  SIGNAL(buttonClicked()), SLOT(showMinimized()));

        standAloneWindow->sceneManager()->appearSceneWindowNow(homeButtonPanel);
    }
}

void MDialogPrivate::_q_onStandAloneDialogDisappeared()
{
    Q_Q(MDialog);
    Q_ASSERT(standAloneWindow != 0);

    q->disconnect(SIGNAL(disappeared()), q, SLOT(_q_onStandAloneDialogDisappeared()));

    standAloneWindow->setScene(0);
    standAloneWindow->deleteLater();
    standAloneWindow = 0;

    // Remove dialog from scene otherwise scene will delete dialog
    // on scene's destructor
    if (q->scene()) {
        q->scene()->removeItem(q);
    }

    if (homeButtonPanel) {
        if (homeButtonPanel->sceneManager())
            homeButtonPanel->sceneManager()->disappearSceneWindowNow(homeButtonPanel);
        delete homeButtonPanel;
        homeButtonPanel = 0;
    }

    if (suicideAfterDestroyingStandAloneWindow) {
        q->deleteLater();
    }
}

bool MDialogPrivate::prepareStandAloneAppearance(MSceneWindow::DeletionPolicy policy)
{
    Q_Q(MDialog);
    bool ok = true;

    if (standAloneWindow == 0) {
        standAloneWindow = new MWindow(new MSceneManager);
        standAloneWindow->setTranslucentBackground(true);
#ifdef Q_WS_X11
        standAloneWindow->setAttribute(Qt::WA_X11NetWmWindowTypeDialog, true);
        XSetTransientForHint(QX11Info::display(), standAloneWindow->winId(), MApplication::activeWindow()->winId());
#endif
        q->connect(q, SIGNAL(disappeared()), SLOT(_q_onStandAloneDialogDisappeared()));
    }

    // We only have a home button in the stand-alone window if the
    // the dialog is supposed to be modeless.
    updateStandAloneHomeButtonVisibility();

    // Dialog will handle its own deletion policy instead of scene manager
    // since in this case the dialog owns the scene manager and not the other
    // way around
    suicideAfterDestroyingStandAloneWindow = (policy == MSceneWindow::DestroyWhenDone);

    standAloneWindow->show();

    // Check whether the dialog is already present in some scene manager
    if (shown) {
        if (q->sceneManager() != standAloneWindow->sceneManager()) {
            q->sceneManager()->disappearSceneWindowNow(q);
        } else {
            ok = false;
        }
    }

    return ok;
}

void MDialogPrivate::updateButtonClickedMappings()
{
    Q_Q(MDialog);

    if (buttonClickedMapper) {
        delete buttonClickedMapper;
        buttonClickedMapper = 0;
    }

    buttonClickedMapper = new QSignalMapper();
    q->connect(buttonClickedMapper, SIGNAL(mapped(QObject *)),
               SLOT(_q_buttonClicked(QObject *)));

    MButtonModel *buttonModel;
    MDialogButtonsList buttonModelsList = q->model()->buttons();

    const int buttonModelsSize = buttonModelsList.size();
    for (int i = 0; i < buttonModelsSize; ++i) {
        buttonModel = buttonModelsList[i];

        buttonClickedMapper->connect(buttonModel, SIGNAL(clicked()), SLOT(map()));
        buttonClickedMapper->setMapping(buttonModel, buttonModel);
    }
}

int MDialogPrivate::resultFromStandardButtonId(int buttonId)
{
    switch (buttonId) {
    case M::NoStandardButton:
    case M::OkButton:
    case M::SaveButton:
    case M::SaveAllButton:
    case M::OpenButton:
    case M::YesButton:
    case M::YesToAllButton:
    case M::RetryButton:
    case M::ApplyButton:
    case M::DoneButton:
        return MDialog::Accepted;
    case M::NoButton:
    case M::NoToAllButton:
    case M::AbortButton:
    case M::IgnoreButton:
    case M::CloseButton:
    case M::CancelButton:
    case M::DiscardButton:
    case M::HelpButton:
    case M::ResetButton:
    case M::RestoreDefaultsButton:
        return MDialog::Rejected;
    default:
        //Non-standard buttons should be handled by NoStandardButton case.
        //This should not happen.
        return MDialog::Accepted;
    };
}

MDialog::MDialog() :
    MSceneWindow(new MDialogPrivate(), new MDialogModel(), MSceneWindow::Dialog, QString())
{
    Q_D(MDialog);

    d->init();

    model()->setResultCode(MDialog::Rejected);
}

MDialog::MDialog(const QString &title, M::StandardButtons buttons) :
    MSceneWindow(new MDialogPrivate(), new MDialogModel(), MSceneWindow::Dialog, QString())
{
    Q_D(MDialog);

    d->init();

    model()->setResultCode(MDialog::Rejected);

    setTitle(title);

    d->addStandardButtons(buttons);
}

MDialog::MDialog(MDialogPrivate *dd, MDialogModel *model, MSceneWindow::WindowType windowType) :
    MSceneWindow(dd, model, windowType, QString())
{
    Q_D(MDialog);

    d->init();

    model->setResultCode(MDialog::Rejected);
}

MDialog::MDialog(MDialogPrivate *dd, M::StandardButtons buttons,
                     MDialogModel *model, MSceneWindow::WindowType windowType) :
    MSceneWindow(dd, model, windowType, QString())
{
    Q_D(MDialog);

    d->init();

    model->setResultCode(MDialog::Rejected);

    d->addStandardButtons(buttons);
}

MDialog::~MDialog()
{
}

QString MDialog::title() const
{
    return model()->title();
}

void MDialog::setTitle(const QString &title)
{
    model()->setTitle(title);
}

QGraphicsWidget *MDialog::centralWidget()
{
    return model()->centralWidget();
}

void MDialog::setCentralWidget(QGraphicsWidget *centralWidget)
{
    if (model()->centralWidget())
        delete model()->centralWidget();

    model()->setCentralWidget(centralWidget);
}

void MDialog::addButton(MButtonModel *buttonModel)
{
    model()->addButton(buttonModel);
}

MButtonModel *MDialog::addButton(const QString &text)
{
    MButtonModel *buttonModel = 0;

    buttonModel = new MButtonModel;
    buttonModel->setText(text);
    model()->addButton(buttonModel);

    return buttonModel;
}

MButtonModel *MDialog::addButton(M::StandardButton buttonType)
{
    return model()->addButton(buttonType);
}

void MDialog::removeButton(MButtonModel *buttonModel)
{
    model()->removeButton(buttonModel);
}

MButtonModel *MDialog::button(M::StandardButton which)
{
    return model()->button(which);
}

M::StandardButton MDialog::standardButton(MButtonModel *buttonModel) const
{
    return model()->standardButton(buttonModel);
}

void MDialog::appear(MSceneWindow::DeletionPolicy policy)
{
    Q_D(MDialog);
    d->appear(policy);
}

void MDialog::appear(MWindow *window, MSceneWindow::DeletionPolicy policy)
{
    Q_D(MDialog);

    if (window) {
        MSceneWindow::appear(window, policy);
    } else {
        d->appear(policy);
    }
}

void MDialog::accept()
{
    done(Accepted);
}

void MDialog::reject()
{
    done(Rejected);
}

void MDialog::done(int result)
{
    setResult(result);

    emit finished(result);
    if (result == MDialog::Accepted)
        emit accepted();
    else if (result == MDialog::Rejected)
        emit rejected();

    if (sceneManager())
        sceneManager()->disappearSceneWindow(this);
}

int MDialog::exec(MWindow *window)
{
    Q_D(MDialog);
    MSceneManager *targetSceneManager = 0;
    int result;

    d->clickedButton = 0;
    d->policy = MSceneWindow::KeepWhenDone;

    if (window) {
        targetSceneManager = window->sceneManager();
    } else {
        if (isSystemModal()) {
            d->prepareStandAloneAppearance(KeepWhenDone);
            targetSceneManager = d->standAloneWindow->sceneManager();
        } else {
            window = MApplication::activeWindow();
            if (window) {
                targetSceneManager = window->sceneManager();
            } else {
                mWarning("MDialog") << "Cannot appear. No MWindow currently active.";
            }
        }
    }

    if (targetSceneManager) {
        result = targetSceneManager->execDialog(this);
    } else {
        result = Rejected;
    }

    return result;
}

MButtonModel *MDialog::clickedButton() const
{
    Q_D(const MDialog);

    return d->clickedButton;
}

int MDialog::result() const
{
    return model()->resultCode();
}

void MDialog::setResult(int result)
{
    model()->setResultCode(result);
}

bool MDialog::isButtonBoxVisible() const
{
    return model()->buttonBoxVisible();
}

void MDialog::setButtonBoxVisible(bool visible)
{
    model()->setButtonBoxVisible(visible);
}

bool MDialog::isCloseButtonVisible() const
{
    return model()->closeButtonVisible();
}

void MDialog::setCloseButtonVisible(bool visible)
{
    model()->setCloseButtonVisible(visible);
}

bool MDialog::isProgressIndicatorVisible() const
{
    return model()->progressIndicatorVisible();
}

void MDialog::setProgressIndicatorVisible(bool visible)
{
    model()->setProgressIndicatorVisible(visible);
}

bool MDialog::isTitleBarVisible() const
{
    return model()->titleBarVisible();
}

void MDialog::setTitleBarVisible(bool visible)
{
    model()->setTitleBarVisible(visible);
}

bool MDialog::isSystemModal() const
{
    return model()->systemModal();
}

void MDialog::setSystemModal(bool systemModal)
{
    model()->setSystemModal(systemModal);
}

void MDialog::setLayout(QGraphicsLayout *layout)
{
    Q_D(MDialog);
    mWarning("MDialog:") << "Please don't change the layout directly.";
    d->dumbMode = true;
    QGraphicsWidget::setLayout(layout);
}

QGraphicsLayout *MDialog::layout()
{
    Q_D(MDialog);
    mWarning("MDialog:") << "Please don't change the layout directly.";
    d->dumbMode = true;
    return QGraphicsWidget::layout();
}

void MDialog::updateData(const QList<const char *>& modifications)
{
    MSceneWindow::updateData(modifications);
    Q_D(MDialog);

    if (modifications.contains(MDialogModel::Buttons)) {
        d->updateButtonClickedMappings();
        d->clickedButton = 0;
    }
}

void MDialog::setupModel()
{
    MSceneWindow::setupModel();
    Q_D(MDialog);
    d->updateButtonClickedMappings();
    d->clickedButton = 0;
}

void MDialog::dismissEvent(MDismissEvent *event)
{
    setResult(Rejected);
    emit finished(result());
    emit rejected();

    event->accept();
}

#include "moc_mdialog.cpp"
<|endoftext|>